About sorting (direct insertion sort, selection sort, bubble sort, merge sort, quick sort)

About sorting (direct insertion sort, selection sort, bubble sort, merge sort, quick sort)

Summarized the knowledge about sorting, the understanding is deeper than before~


#include<bits/stdc++.h>
using namespace std ;
//注意:数组下标都是从1开始的!
//所有排序都是升序排序

void Insert_Sort(int a[] ,int n){
    
    //直接插入排序(i前面是已经排好序的了)
    for(int i =2 ;i <= n; i++ ){
    
    
        a[0] = a[i] ;//哨兵,记录当前的值,防止越界
        int j ;
        for(j = i-1 ;a[j]>a[0] ;j--){
    
    //后移动
            a[j+1] = a[j];
        }
        a[j+1] = a[0] ;
    }
}
void Insert_Sort2(int a[] ,int n){
    
    //直接插入排序的优化——折半插入排序
    for(int i = 2;i<= n ;i++ ){
    
    //折半是在已经排好的序列折半
        a[0] = a[i] ;
        int low = 1 , high = i -1 ;
        while (low <= high){
    
    
            int mid = (high + low )/ 2 ;
            if(a[mid ] > a[0 ]){
    
    //a[0]在左边
                high = mid - 1 ;
            }else{
    
    //a[0]在右边
                low = mid + 1 ;
            }
        }
        for(int j = i-1 ;j >=high+1 ;j-- ){
    
    //元素后移动
            a[j+1] = a[j];
        }
        a[high + 1 ] = a[0];
    }
}

void Select_Sort(int a[],int n){
    
    //选择排序(在这每次选择的是最小值的下标),每次能确定一个数的位置
    for(int i = 1 ;i<= n ;i++ ){
    
    
        int min = i ;
        for(int j = i+1 ;j<=n ;j++ ){
    
    
            if(a[min] > a[j]){
    
    
                min = j ;
            }
        }
        if(min != i ){
    
    
            swap(a[min], a[i]);
        }

    }
}

void Bubble_Sort(int a[] ,int n){
    
    //冒泡排序,后面往前冒泡,每次能确定一个数的位置
    int flag = 1 ;//做小小的优化————当某一轮,没有进行交换的时候,说明排序以及排好了(自行模拟)
    for(int i = 1 ;i <=n && flag; i++ ){
    
    
        flag= 0 ;
        for(int j = n-1 ;j>=i ;j -- ){
    
    
            if(a[j+1] < a[j]){
    
    
                flag = 1 ;
                swap(a[j+1], a[j]);
            }
        }
    }
}

int b[100 ];//归并排序需要一个辅助数组,一般是 2路归并
void Merge_OP(int a[] ,int low ,int mid ,int high ){
    
    //归并排序,low->mid , mid+1 -> high 两部分
    int i = low ,j =mid+1 ,k = low ;//k是移动辅助数组的下标
    while (i <= mid && j<= high ){
    
    
        if(a[i] < a[j]){
    
    
            b[k++] = a[i++ ];
        }else {
    
    
            b[k++ ] = a[j++];
        }
    }
    while (i <= mid){
    
       // 注意有 " = "
        b[k++ ] = a[i++ ];
    }
    while (j <= high) {
    
    
        b[k++] = a[j++ ];
    }
    for(i = low ;i <= high ;i++ ){
    
    
        a[i] = b[i ];
    }
    
}
void Merge_Sort(int a[] ,int low ,int high ){
    
    //归并也是递归,先排,在合并
    if(low < high ){
    
    
        int mid = (low + high )/2;
        Merge_Sort(a , low ,mid );
        Merge_Sort(a , mid+1 , high);
        
        Merge_OP(a,low ,mid ,high);
        
    }
}

//大哥大 —— 快速排序,在这里写两种方式
//快排1
int Partition1(int a[],int low ,int high ){
    
    //第一种,取第一个数作为枢纽
    int pivort_key = a[low ];
    int i = low ,j = high ;
    
    while (i<j ){
    
    
        while (i < j && a[j] > pivort_key){
    
    //后面找比枢纽小的,换到前面
            j-- ;
        }
        a[i] = a[j] ;//这里也可以用swap交换,但是这样直接赋值的时间复杂度要低(算是个优化,减少了比对次数)
        while (i < j && a[i] < pivort_key ){
    
    //前面找比枢纽大的,换到后面
            i ++ ;
        }
        a[j] = a[i];
    }
    a[i] = pivort_key;//最终确认枢纽的值(注意,如果前面用的swap,这里就不用赋值了)
    
    return i ;//每轮确定一个数的位置(pivort_key),他左边的定比他小,右边的定比他大
}
void Quick_Sort1(int a[] ,int low ,int high ){
    
    //先分为两边,在排序(区分归并)
    if(low < high ){
    
    //不管什么时候,递归先写递归边界
        int pivort = Partition1(a, low , high);
        
        Quick_Sort1(a, low , pivort -1 );
        Quick_Sort1(a, pivort + 1 , high );
    }
}
//快排2
//快速排序——随机数做种子
int Partition2(int a[] ,int low ,int high ){
    
    
    srand((unsigned)time(NULL));//取系统时间作为随机数的种子
    int m = low + rand() %(high - low +1 );//注意取余
    swap(a[m], a[low ]);//将枢纽元素交换到最左边位置
    int i = low ;
    for(int j = i+1 ;j <= high ;j++  ){
    
    //去后面找,比枢纽小的,换到前面,也就是说,i位置左边的数,定小于枢纽
        if(a[j] < a[low ]){
    
    
            swap(a[++i], a[j]);//作用同下面两行
//            i++ ;
//            swap(a[i], a[j]);
        }
    }
    swap(a[i], a[low ]);//j走完了,说明数组中没有比当前枢纽值小的数了,此时i的位置就是枢纽应该的位置,交换
    return i ;
}
void Quick_Sort2(int a[] ,int low ,int high ){
    
    //递归部分无变化
    if(low < high ){
    
    
        int pivort = Partition2(a, low , high);
        
        Quick_Sort1(a, low , pivort -1 );
        Quick_Sort1(a, pivort + 1 , high );
    }
}


void Print(int a[],int n){
    
    //打印
    for(int i = 1 ;i<= n ;i++ ){
    
    
        cout << a[i] <<" ";
    }
    cout << endl;
}

int main(){
    
    
    int a[] = {
    
    0,1,3,2,9,5,6,7,4,8};//0没用,排序都是从下标为1开始的
    cout << "待排序序列:" ;
    Print(a, sizeof(a)/4 -1 );
    
//    cout << "直接插入排序:" ;
//    Insert_Sort(a, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );
    
//    cout << "折半插入排序:" ;
//    Insert_Sort2(a, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );
    
//    cout << "选择排序:" ;
//    Select_Sort(a, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );
    
//    cout << "冒泡排序:" ;
//    Bubble_Sort(a, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );
    
//    cout << "归并排序:" ;
//    Merge_Sort(a, 1, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );
    
//    cout << "快速排序1:" ;
//    Quick_Sort1(a, 1, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );
//
//    cout << "快速排序2:" ;
//    Quick_Sort2(a, 1, sizeof(a)/4 -1 );//长度要-1
//    Print(a,sizeof(a)/4 -1 );

    return  0 ;
}

Guess you like

Origin blog.csdn.net/qq_41015402/article/details/109430611