基本的排序算法C++實現(插入排序,選擇排序,冒泡排序,歸並排序,快速排序,最大堆排序,希爾排序)


博主歡迎轉載,但請給出本文鏈接,我尊重你,你尊重我,謝謝~
http://www.cnblogs.com/chenxiwenruo/p/8529525.html
特別不喜歡那些隨便轉載別人的原創文章又不給出鏈接的
所以不准偷偷復制博主的博客噢~~

 

最近適當復習了下基本的排序算法,雖然做題的時候一般都直接用sort了事,但基本的排序原理還是要了解的,所以把常見的排序又重新寫了下。

基本的插入、選擇、冒泡就不說了,歸並排序、快速排序可以網上搜算法導論的學習,也很簡單。

1.插入排序

void insertSort(int a[],int len){
    for(int i=1;i<len;i++){
        int tmp=a[i];
        int j=i-1;
        while(j>=0 && tmp<a[j]){
            a[j+1]=a[j];
            j--;
        }
        a[j+1]=tmp;
    }
}
View Code

 

2.選擇排序

void selectSort(int a[],int len){
    for(int i=0;i<len-1;i++){
        int minidx=i;
        for(int j=i+1;j<len;j++){
            if(a[j]<a[minidx]){
                minidx=j;
            }
        }
        if(a[i]>a[minidx]){
            int tmp=a[i];
            a[i]=a[minidx];
            a[minidx]=tmp;
        }
    }
}
View Code

 

3.冒泡排序

void bubbleSort(int a[],int len){
    int tmp;
    for(int i=0;i<len-1;i++){
        bool flag=true;
        for(int j=0;j<len-i-1;j++){
            if(a[j]>a[j+1]){
                tmp=a[j+1];
                a[j+1]=a[j];
                a[j]=tmp;
                flag=false;
            }
        }
        if(flag)
            break;
    }
}
View Code

 

4.歸並排序O(NlgN)

#define INF 0x3f3f3f3f
/*
將[l,mid]和[mid+1,r]兩個區間進行合並,每次取兩個開頭最小的那個
*/
void merges(int a[],int l,int mid,int r){
    int len1=mid-l+1;
    int len2=r-mid;
    int L[len1+1],R[len2+1];
    for(int i=0;i<len1;i++)
        L[i]=a[l+i];
    for(int i=0;i<len2;i++)
        R[i]=a[mid+1+i];
    L[len1]=INF;
    R[len2]=INF;
    int left=0,right=0;
    for(int k=l;k<=r;k++){
        if(L[left]<=R[right]){
            a[k]=L[left];
            left++;
        }
        else{
            a[k]=R[right];
            right++;
        }
    }
}
//對區間[l,r]進行歸並排序
void mergeSort(int a[],int l,int r){
    if(l<r){
        int mid=(r+l)/2;
        mergeSort(a,l,mid);
        mergeSort(a,mid+1,r);
        merges(a,l,mid,r);
    }
}
View Code

 

5.快速排序O(NlgN)

/*
以最后a[r]為划分點,將數組a划分成兩個部分
前部分<=a[r],后部分>a[r]
最后返回a[r]的索引
*/
int quick_partition(int a[],int l,int r){
    int x=a[r];
    int i=l-1;
    for(int j=l;j<r;j++){
        if(a[j]<=x){
            i++;
            swap(a[i],a[j]);
        }
    }
    swap(a[i+1],a[r]);
    return i+1;

}
void quickSort(int a[],int l,int r){
    if(l<r){
        int mid=quick_partition(a,l,r);
        quickSort(a,l,mid-1);
        quickSort(a,mid+1,r);
    }
}
View Code

 

6.最大堆排序O(NlgN)

//----------------堆排序O(NlgN)最大堆的實現--------------------------
/*
將最大堆的根節點和末尾交換后,可能破壞了最大堆的性質,所以要進行更新
*/
void heap_update(int a[],int i,int heap_size){
    int l=i*2+1;
    int r=i*2+2;
    int large=i;
    if(l<heap_size && a[l]>a[large])
        large=l;
    if(r<heap_size && a[r]>a[large])
        large=r;
    if(large!=i){
        swap(a[i],a[large]);
        heap_update(a,large,heap_size);
    }
}
/*
將val插入到數組a的末尾,並進行最大堆的維護
*/
void heap_insert(int a[],int val,int heap_size){
    heap_size++;
    a[heap_size-1]=val;
    int idx=heap_size-1;
    while(idx>0 && a[idx/2]<a[idx]){
        swap(a[idx/2],a[idx]);
        idx=idx>>1;
    }
}
void heapSort(int a[],int len){
    //構建最大堆
    for(int i=0;i<len;i++)
        heap_insert(a,a[i],i);
    for(int i=len-1;i>=0;i--){
        swap(a[0],a[i]);
        heap_update(a,0,i);  //每次heap_size減小1的
    }
}
View Code

 

7.希爾排序

最近突然遇到希爾排序,之前沒聽過,所以就了解一下,不專門寫介紹了,給一篇鏈接吧,講得挺詳細的

https://www.cnblogs.com/chengxiao/p/6104371.html

希爾排序對於增量序列(即gap)的選擇很重要,會影響到排序的性能,通常都采用gap=length/2。

希爾排序是可以突破O(N^2)的,但gap/=2的情況下最壞時間復雜度依然為O(N^2),一些優化過后的序列最壞情況可以到O(N^3/2)。

/*
https://www.cnblogs.com/chengxiao/p/6104371.html
希爾排序
*/
void shellsort(int a[],int len){
    //划分成gap個組
    for(int gap=len/2;gap>0;gap/=2){
        //從第gap個元素,逐個對其所在組進行插入排序操作
        //而不需要for每個組進行操作
        for(int i=gap;i<len;i++){
            int j=i-gap;
            //插入排序采用交換法即可
            while(j>=0 && a[j]>a[j+gap]){
                swap(a[j],a[j+gap]);
                j-=gap;
            }
        }
        /*
        printf("gap:%d\n",gap);
        for(int i=0;i<len;i++)
            printf("%d ",a[i]);
        printf("\n");
        */
    }
}
View Code

 

完整的測試代碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cstdlib>
#include <ctime>
using namespace std;
//----------------插入排序--------------------------
void insertSort(int a[],int len){
    for(int i=1;i<len;i++){
        int tmp=a[i];
        int j=i-1;
        while(j>=0 && tmp<a[j]){
            a[j+1]=a[j];
            j--;
        }
        a[j+1]=tmp;
    }
}
//----------------選擇排序--------------------------
void selectSort(int a[],int len){
    for(int i=0;i<len-1;i++){
        int minidx=i;
        for(int j=i+1;j<len;j++){
            if(a[j]<a[minidx]){
                minidx=j;
            }
        }
        if(a[i]>a[minidx]){
            int tmp=a[i];
            a[i]=a[minidx];
            a[minidx]=tmp;
        }
    }
}
//----------------冒泡排序--------------------------
void bubbleSort(int a[],int len){
    int tmp;
    for(int i=0;i<len-1;i++){
        bool flag=true;
        for(int j=0;j<len-i-1;j++){
            if(a[j]>a[j+1]){
                tmp=a[j+1];
                a[j+1]=a[j];
                a[j]=tmp;
                flag=false;
            }
        }
        if(flag)
            break;
    }
}
//----------------歸並排序O(NlgN)--------------------------
#define INF 0x3f3f3f3f
/*
將[l,mid]和[mid+1,r]兩個區間進行合並,每次取兩個開頭最小的那個
*/
void merges(int a[],int l,int mid,int r){
    int len1=mid-l+1;
    int len2=r-mid;
    int L[len1+1],R[len2+1];
    for(int i=0;i<len1;i++)
        L[i]=a[l+i];
    for(int i=0;i<len2;i++)
        R[i]=a[mid+1+i];
    L[len1]=INF;
    R[len2]=INF;
    int left=0,right=0;
    for(int k=l;k<=r;k++){
        if(L[left]<=R[right]){
            a[k]=L[left];
            left++;
        }
        else{
            a[k]=R[right];
            right++;
        }
    }
}
//對區間[l,r]進行歸並排序
void mergeSort(int a[],int l,int r){
    if(l<r){
        int mid=(r+l)/2;
        mergeSort(a,l,mid);
        mergeSort(a,mid+1,r);
        merges(a,l,mid,r);
    }
}
//----------------快速排序O(NlgN)--------------------------
/*
以最后a[r]為划分點,將數組a划分成兩個部分
前部分<=a[r],后部分>a[r]
最后返回a[r]的索引
*/
int quick_partition(int a[],int l,int r){
    int x=a[r];
    int i=l-1;
    for(int j=l;j<r;j++){
        if(a[j]<=x){
            i++;
            swap(a[i],a[j]);
        }
    }
    swap(a[i+1],a[r]);
    return i+1;

}
void quickSort(int a[],int l,int r){
    if(l<r){
        int mid=quick_partition(a,l,r);
        quickSort(a,l,mid-1);
        quickSort(a,mid+1,r);
    }
}


int main()
{
    int num=10;
    int a[num];
    srand((unsigned)time(NULL));
    for(int i=0;i<num;i++){
        a[i]=rand()%20;
        printf("%d ",a[i]);
    }
    printf("\n");
    quickSort(a,0,num-1);
    for(int i=0;i<num;i++){
        printf("%d ",a[i]);
    }
    return 0;
}
View Code

 

最后,當然排序最省力的就是C++中的自定義排序了,直接用algorithm中的sort即可。

#include <algorithm>
bool cmp(int a,int b){
    return a>b; 
}

sort(a,a+n); //a為數組,n為數組的長度,默認是從小到大排序
sort(a,a+n,cmp);//cmp即為自定義比較函數,此處是從大到小排序。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM