[C++은 삽입정렬, 힐정렬, 버블정렬, 퀵정렬, 선택정렬 구현]

C++를 사용하여 삽입 정렬, 힐 정렬, 버블 정렬, 빠른 정렬 및 선택 정렬 알고리즘을 구현합니다.

1. 삽입 정렬

삽입 정렬은 일반적으로 직접 삽입 정렬이라고도 합니다. 적은 수의 요소를 정렬하는 효율적인 알고리즘입니다. 삽입정렬은 가장 간단한 정렬 방법으로, 정렬된 정렬된 목록에 레코드를 삽입하여 레코드 수가 1 증가한 새로운 정렬된 목록을 생성하는 것이 기본 아이디어입니다. 구현 과정에서 이중 계층 루프를 사용하는데, 외부 루프는 첫 번째 요소를 제외한 모든 요소를 ​​찾고, 내부 루프는 현재 요소 앞의 정렬된 목록에서 삽입할 위치를 찾아 이동합니다.

삽입 정렬은 많은 사람들이 포커 패를 정렬하는 것처럼 작동합니다. 우리는 빈 왼손으로 시작하고 카드는 테이블에 뒤집어 놓습니다. 그런 다음 테이블에서 한 번에 한 장의 카드를 가져와 왼손의 올바른 위치에 삽입합니다. 카드의 올바른 위치를 찾기 위해 이미 손에 있는 모든 카드와 오른쪽에서 왼쪽으로 카드를 비교합니다. 왼손에 들고 있는 카드는 항상 정렬되어 있으며, 이 카드가 테이블 더미의 맨 위 카드인 것으로 밝혀졌습니다.

삽입정렬이란 정렬할 요소들 중에서 이전 n-1(여기서 n>=2)의 숫자가 이미 순서가 있다고 가정하고, 이제 n번째 숫자를 이전에 배열한 시퀀스에 삽입한 후 자신의 위치에 맞는 것을 찾는 것을 의미합니다. , 따라서 n번째 숫자에 삽입된 시퀀스도 순서대로 정렬됩니다. 이 방법에 따르면 전체 시퀀스가 ​​정렬 될 때까지 모든 요소가 삽입되는 삽입 정렬이라고합니다.

#include<iostream>
using namespace std;

int main()
{
    
    
	int arr[6]={
    
    9,7,6,5,4,3};
	//遍历数组,依次进行比较 
	for(int i=0;i<5;i++){
    
    
		/*
		比较i和i+1,如果升序排序,则判断第i个元素是否大于第i+1个
		元素,如果是,则将第i+1个元素依次与之前的所有元素进行比较并
		排序,完成后将第i个元素插入到第i+1个元素的位置上。降序也是
		同样的原理。 
		*/ 
		if(arr[i]>arr[i+1]){
    
    
			//交换
			//从第i个元素开始交换 
			int j=i;
			//将需要插入的元素使用变量temp保存 
			int temp=arr[i+1];
			/**
			将第i个元素之前的所有元素进行一次重新排序,保证第0-i个元素
			之间是排好序的。 
			*/ 
			while(j>=0&&temp<arr[j]){
    
    
				arr[j+1]=arr[j];
				j--;
			}
			arr[j+1]=temp;
		}
	}
	//打印输出排序结果 
	for(int i=0;i<6;i++){
    
    
		cout<<arr[i]<<" ";
	}
 } 

2. 힐 정렬

Shell's Sort는 "Diminishing Increment Sort"라고도 하는 삽입 정렬의 일종으로, 직접 삽입 정렬 알고리즘의 보다 효율적이고 개선된 버전입니다. 힐 정렬은 불안정한 정렬 알고리즘입니다. 이 방법은 1959년에 제안된 DLShell의 이름을 따서 명명되었습니다.

힐정렬은 특정 첨자 증분만큼 레코드를 그룹화하고 직접 삽입 정렬 알고리즘을 사용하여 각 그룹을 정렬하는 방식으로 증분이 점차 감소함에 따라 각 그룹에는 점점 더 많은 키워드가 포함됩니다. 증분이 1로 감소하면, 전체 파일이 방금 그룹화되면 알고리즘이 종료됩니다.

#include<iostream>
using namespace std;

int main()
{
    
    
	int arr[6]={
    
    9,7,6,5,4,3};
	//控制步长 
	for(int gap=6/2;gap>0;gap/=2){
    
    
		//遍历所有的组 
		for(int i=0;i<gap;i++){
    
    
			//遍历每个组中的所有元素 
			for(int j=i-gap;j>=0;j-=gap){
    
    
				/*
				比较第j个元素和第j+gap个元素,不满足排序规则的交换
				元素顺序。 
				*/ 
				if(arr[j]>arr[j+gap]){
    
    
					int t=arr[j];
					arr[j]=arr[j+gap];
					arr[j+gap]=t;
				}
			}
		}
	} 
	//打印输出排序结果 
	for(int i=0;i<6;i++){
    
    
		cout<<arr[i]<<" ";
	}
 } 

3. 버블 정렬

버블 정렬은 컴퓨터 과학 분야에서 비교적 간단한 정렬 알고리즘입니다.

정렬할 요소의 열을 반복적으로 방문하여 인접한 두 요소를 차례로 비교하고 순서(예: 큰 것에서 작은 것, 첫 글자 Z에서 A로)가 잘못된 경우 교환합니다. 요소 방문 작업은 인접한 요소를 교환할 필요가 없을 때까지, 즉 요소 열이 정렬될 때까지 반복됩니다.

이 알고리즘의 이름은 탄산 음료의 이산화탄소 거품이 결국 맨 위로 떠오르는 것처럼 더 작은 요소가 교환을 통해 시퀀스의 맨 위로 천천히 "떠오른다"(오름차순 또는 내림차순)는 사실에서 유래되었습니다. , 따라서 "버블링"이라는 이름입니다. 정렬".

버블 정렬 알고리즘의 원리는 다음과 같습니다.

  1. 인접한 요소를 비교합니다. 첫 번째가 두 번째보다 크면 둘 다 교환하십시오.
  2. 시작 부분의 첫 번째 쌍에서 끝 부분의 마지막 쌍까지 각 인접 요소 쌍에 대해 동일한 작업을 수행합니다. 이 시점에서 마지막 요소는 가장 큰 숫자여야 합니다.
  3. 마지막 요소를 제외한 모든 요소에 대해 위의 단계를 반복합니다.
  4. 비교할 숫자 쌍이 없을 때까지 매번 더 적은 수의 요소에 대해 위의 단계를 계속 반복합니다.
#include <iostream>
using namespace std;

int main()
{
    
    
    int array[8] = {
    
    8,7,6,5,4,3,2,1};
    //打印输出排序前的数组 
    cout<<"排序前的数组为:";
    for (int i = 0; i < 8; i++){
    
    
        cout<<array[i]<<" ";
    }
    //冒泡排序 
    for(int i=0;i<8;i++){
    
    
    	for(int j=0;j<8-1-i;j++){
    
     
    		if(array[j]>array[j+1]){
    
    
    			int temp=array[j];
    			array[j]=array[j+1];
    			array[j+1]=temp;
			}
		}
	}
    //打印输出排序后的数组 
    cout<<"\n排序后的数组为:";
    for (int i = 0; i < 8; i++){
    
    
        cout<<array[i]<<" ";
    }
    
    return 0;
}

4. 퀵 정렬

퀵 정렬 알고리즘은 다중 비교 및 ​​교환을 통해 정렬을 구현하며 정렬 프로세스는 다음과 같습니다.

(1) 먼저 컷오프 값을 설정하고 컷오프 값을 통해 어레이를 좌우 부분으로 나눕니다.

(2) 배열 오른쪽에 컷오프 값보다 크거나 같은 데이터를 수집하고 배열 왼쪽에 컷오프 값보다 작은 데이터를 수집합니다. 이때 왼쪽 부분의 각 요소는 컷오프 값보다 작고 오른쪽 부분의 각 요소는 컷오프 값보다 크거나 같습니다.

(3) 그런 다음 왼쪽 및 오른쪽 데이터를 독립적으로 정렬할 수 있습니다. 왼쪽 배열 데이터의 경우 경계값을 취하여 데이터의 이 부분을 왼쪽과 오른쪽 부분으로 나눌 수 있으며 더 작은 값은 왼쪽에, 큰 값은 오른쪽에 배치됩니다. 오른쪽의 배열 데이터도 유사하게 처리할 수 있습니다.

(4) 위 과정을 반복하면 이것이 재귀적 정의임을 알 수 있다. 왼쪽 부분을 재귀적으로 정렬한 후 오른쪽 부분의 순서를 재귀적으로 정렬합니다. 왼쪽과 오른쪽 부분의 데이터 정렬이 완료되면 전체 배열의 정렬도 완료됩니다.
원칙

정렬할 배열이 A[0]...A[N-1]이라고 가정하고 먼저 데이터(일반적으로 배열의 첫 번째 숫자)를 임의로 키 데이터로 선택한 다음 그보다 작은 숫자를 모두 넣습니다. 왼쪽에는 그것보다 큰 모든 숫자가 오른쪽에 배치되며 이 프로세스를 퀵 정렬이라고 합니다. 퀵 정렬은 안정적인 정렬 알고리즘이 아니라는 점에 유의할 필요가 있습니다. 즉, 여러 개의 동일한 값의 상대 위치가 알고리즘의 끝에서 변경될 수 있습니다.

원패스 퀵 정렬 알고리즘은 다음과 같습니다.

1) 정렬이 시작될 때 두 개의 변수 i, j를 설정합니다: i=0, j=N-1;

2) 첫 번째 배열 요소를 키 데이터로 key 에 할당합니다 . 즉, key = A[0];

3) j부터 앞으로 찾기, 즉 뒤에서부터 앞으로 찾기(j–) 키보다 작은 첫 번째 값 A[j]를 찾아 A[ j ]와 A[i의 값을 교환 ];

4) i부터 역방향 탐색, 즉 앞에서부터 역방향 탐색(i++) 키 보다 큰 첫 번째 A[i]를 찾아 A[i]와 A[j]의 값을 교환하는 단계;

5) i까지 3단계와 4단계를 반복합니다.j; 3단계와 4단계에서 정규화된 값을 찾을 수 없습니다. 즉, 3의 A[j]가 보다 작지 않고 4의 A[i]가 보다 크지 않으면 j의 값을 변경합니다. 그리고 i가 j=j-1, i=i+1이 되도록, 찾을 때까지. 조건에 맞는 값을 찾아 교환을 하면 i 포인터와 j 포인터의 위치는 그대로 유지된다. 또한, 나는j의 과정은 정확히 i++ 또는 j–가 완료되는 시점이어야 하며 이 시점에서 주기가 종료됩니다.

데모 정렬

초기 시퀀스 {xi}가 5, 3, 7, 6, 4, 1, 0, 2, 9, 10, 8이라고 가정합니다.

이때, ref=5, i=1, j=11, 뒤에서 앞으로 보면 5보다 작은 첫 번째 숫자는 x8=2이므로 순서는 2, 3, 7, 6, 4, 1, 0, 5, 9, 10, 8.

이때 i=1, j=8, 앞에서 뒤로 보면 5보다 큰 첫 번째 숫자는 x3=7이므로 순서는 2, 3, 5, 6, 4, 1, 0, 7, 9입니다. , 10, 8.

이때 i=3, j=8, 8번째 자리부터 내다보면 5보다 작은 첫 번째 숫자는 x7=0이므로 2, 3, 0, 6, 4, 1, 5, 7, 9, 10, 8.

이때 i=3, j=7, 3번째부터 보면 5보다 큰 수는 x4=6이므로 2, 3, 0, 5, 4, 1, 6, 7, 9, 10 , 8.

이때 i=4, j=7, 7번째 자리부터 내다보면 5보다 작은 첫 번째 숫자는 x6=1이므로 2, 3, 0, 1, 4, 5, 6, 7, 9, 10, 8.

이때, i=4, j=6, 4위부터 검색하여 6위까지 5보다 큰 숫자가 있고, 이때 i=j=6, ref는 구분선이 되고 앞의 숫자는 그것보다 작고 후속 숫자는 그것보다 큽니다.전후 두 부분에 대해 동일한 방법으로 정렬할 수 있습니다.

#include <iostream>
 
using namespace std;
 
void Qsort(int arr[], int low, int high){
    
    
    if (high <= low){
    
    
    	return;
	}
	
    int left = low;
    int right = high;
    int key = arr[low];
    
    while (true)
    {
    
    
        //将比key小的值放key左边,比key大的值放key右边 
		/*从左向右找比key大的值*/
        while (arr[left] <= key)
        {
    
    
            left++;//从左往右,下标递增 
            //当遍历到最后一个元素时,结束循环 
            if (left == high){
    
    
                break;
            }
        }
        /*从右向左找比key小的值*/
        while (arr[right] >= key)
        {
    
    
            right--; //从右往左,下标递减 
            //当遍历到第一个元素时,结束循环 
			if (right == low){
    
    
                break;
            }
        }
//        cout<<"left:"<<left<<" right:"<<right<<"\n"; 
        /*
		当比key小的数全在左边,比key大的数全在右边时,表
		示第一次排序完成,结束循环
		*/ 
		if (left >= right){
    
    
        	break;
		}
        /*
		将比key小的数移到左边,比key大的数移到右边,
		交换left,right对应的值
		*/
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }
    /*分别对左右两边的数字进行排序,
	中枢值与right对应值交换*/
    arr[low] = arr[right];
    arr[right] = key;
    Qsort(arr, low, right - 1);
    Qsort(arr, right + 1, high);
}
 
int main()
{
    
    
    int arr[] = {
    
    52, 64, 59, 52, 75, 28, 98, 30, 25};
    //获取数组长度 
	int len = sizeof(arr)/sizeof(arr[0]); 
	//打印排序前的数组
	cout<<"排序前:"; 
    for(int i = 0; i < len; i++)
    {
    
    
        cout << arr[i] << " ";
    }
    //调用快速排序函数 
	Qsort(arr, 0, len- 1);
	//打印排序后的数组 
    cout<<"\n排序后:";
    for(int i = 0; i < len; i++)
    {
    
    
        cout << arr[i] << " ";
    }
    return 0;
}

다섯, 선택 정렬

선택 정렬은 간단하고 직관적인 정렬 알고리즘입니다. 작동 원리는 처음으로 정렬할 데이터 요소 중에서 가장 작은(또는 가장 큰) 요소를 선택하여 시퀀스의 시작 위치에 저장한 다음 나머지 정렬되지 않은 요소 요소에서 가장 작은(또는 가장 큰) 요소를 찾는 것입니다. 정렬된 시퀀스의 끝에 놓습니다. 정렬할 모든 데이터 요소의 수가 0이 될 때까지 계속됩니다. 선택 정렬은 불안정한 정렬 방법입니다.

정렬 아이디어 : 먼저 정렬되지 않은 시퀀스에서 가장 작은(가장 큰) 요소를 찾아 정렬된 시퀀스의 시작 부분에 저장한 다음 계속해서 나머지 정렬되지 않은 요소에서 가장 작은(가장 큰) 요소를 찾은 다음 시퀀스의 끝에 놓습니다. 정렬된 시퀀스 모든 요소가 정렬될 때까지 계속됩니다.

구체적인 구현 방법 :

①초기 상태: 정렬되지 않은 영역은 R[0…n-1](총 n개의 요소)이고 정렬된 영역은 비어 있습니다.

② 1차 분류

변수 i를 설정하고 i가 0에서 n-2로 순환하도록 하고 배열에서 요소 i와 요소 i+1의 크기를 비교합니다. R[i+1]이 R[i]보다 작으면 변수 k를 사용합니다. 그의 위치를 ​​기억하십시오(예: k=i+1). 루프가 끝날 때까지 R에서 가장 작은 숫자의 위치를 ​​찾아야 합니다. 그런 다음 가장 작은 요소가 R의 첫 번째 요소가 아닌 경우 첫 번째 요소가 그와 값을 교환하도록 하여 R[0...0] 및 R[1...n-1]이 되도록 판단합니다. 레코드 수가 1 증가한 새로운 정렬 영역과 레코드 수가 1 감소한 새로운 무질서 영역.

......

③i번째 여행 분류

i번째 정렬이 시작되면 현재 정렬된 영역과 정렬되지 않은 영역은 각각 R[0...i-1]과 R[i...n-1]입니다. 이 정렬은 현재 비순차 영역에서 키가 가장 작은 레코드 R[k]를 선택하고 비순차 영역의 첫 번째 레코드 R과 교환하여 R[0...i] 및 R이 각각 레코드의 개수가 되도록 합니다. 1 증가한 새로운 정렬 영역과 레코드 수가 감소한 새로운 무질서한 영역.

그림 1 예: (최소값을 찾아 선택 정렬)

그림 1 선택 정렬(최소값) 예

#include<iostream>

using namespace std;

/*遍历寻找当前序列中的最小值,返回最小值的下标*/
int selectMin(int arr[],int i,int len){
    
    
	int min=i;
	for(;i<len;i++){
    
    
		if(arr[i]<arr[min]){
    
    
			min=i;
		}
	}
	return min;
}

int main()
{
    
    
	int arr[]={
    
    5,8,2,4,1,6};
	int len=sizeof(arr)/sizeof(arr[0]);
	for(int i=0;i<len;i++){
    
    
        //接收当前序列的最小值下标
		int j=selectMin(arr,i,len);
		//判断最小值是否为当前元素,如果不是,则交换最小值和当前元素的位置
        if(i!=j){
    
    
			int temp=arr[i];
			arr[i]=arr[j];
			arr[j]=temp;
		}
	}
	for(int i=0;i<len;i++){
    
    
		cout<<arr[i]<<" ";
	}
  }  

추천

출처blog.csdn.net/qq_43884946/article/details/130883709