1. 程式人生 > >基礎排序算法

基礎排序算法

基礎 sort -a lec get swa blog comm 交換

七個基礎排序算法(均為內部排序):
直接插入排序
希爾排序
冒泡排序
簡單選擇排序
高速排序
堆排序
二路歸並排序

排序算法穩定性:經過排序後,具有同樣關鍵碼的元素之間的相對次序保持不變,則稱該排序方法是穩定的;否則不穩定。

直接插入排序:

技術分享

void InsertSort(int a[],int n){ // index start at 1, a[0] is temp one 
    int i,j;
    for(i=2;i<=n;i++){
        if(a[i]<a[i-1]){
            a[0]=a[i];
a[i]=a[i-1]; for(j=i-2;a[j]>a[0];j--){ a[j+1]=a[j]; } a[j+1]=a[0]; } } }

直接插入排序是一種穩定的排序,時間復雜度O(n^2),空間復雜度是O(1)

希爾排序:

按增量將元素分成不同的子集,對子集不斷的進行插入排序。
技術分享

void ShellSort(int a[],int n){ // index start at 1, a[0] is temp one 
    int d,i,j,k;
    for(d=n/2
;d>=1;d>>=1){ for(i=d+1;i<=n;i++){ // InsertSort if(a[i]<a[i-d]){ a[0]=a[i]; a[i]=a[i-d]; for(j=i-2*d;j>0&&a[0]<a[j];j-=d){ a[j+d]=a[j]; } a[j+d]=a[0]; } } } }

假設a[i]>a[i-d]始終成立。那麽時間是O(nlogn), 可是在糟糕的情況下是O(n^2)。

空間復雜度是O(1)
希爾排序是一種不穩定的排序方法

冒泡排序:

相鄰元素假設反序兩兩交換,直到全部的位置統統確定下來。
技術分享

void BubbleSort(int a[],int n){ // index start at 1, a[0] is temp one 
    int i,j,k;
    for(i=1;i<=n;i++){
        for(j=1;j<=n-i;j++){
        if(a[j]>a[j+1]) {
            a[j]=a[j]^a[j+1];  a[j+1]=a[j]^a[j+1];   a[j]=a[j]^a[j+1];
        }
    }
    }
}

這是穩定的排序方法,時間復雜度:O(n^2)

高速排序:

選擇一個軸值。使得左邊的元素的值小於它,右邊的元素的值大於它。對於產生的分區反復上訴過程。

該算法是對冒泡排序的改進。
技術分享

int partion(int a[],int start,int end){
    int i=start,j=end;
    int temp=a[start];
    while(i<j){
        while(i<j && a[j]>=temp)  j--;
        a[i]=a[j];  // i are more 
        while(i<j && a[i]<=temp)  i++;
        a[j]=a[i]; // j are more
    }
    a[i]=temp;   // at end , i=j
    return i;
}
void Qsort(int a[],int start,int end){
    if(start<end){
        int d=partion(a,start,end);
        Qsort(a,start,d);
        Qsort(a,d+1,end);
    }
}

高速排序不是一種穩定的排序算法。平均來說,Qsort的時間復雜度是O(nlogn)

簡單選擇排序:

思想:第i趟將待排序記錄r[i……n]中最小的元素和r[i]交換
技術分享

void SelectSort(int a[],int n){
    for(int i=1;i<n;i++){
       int dex=i;
       for(int j=i+1;j<=n;j++){
           if(a[dex]>a[j]) dex=j;   // use the index to compare and find min one
       }
       if(dex!=i)  {
           a[dex]=a[dex]^a[i];   a[i]=a[dex]^a[i];   a[dex]=a[dex]^a[i];  
       }
    }
}

堆排序:

堆分為大根堆和小根堆。父節點比左右孩子大或者小。


維護堆的性質:
技術分享

堆排序思路:先建堆。自下而上建堆。

然後將根節點取出並輸出,再把最後的元素放在根節點上,維護堆。

反復上面的過程。
技術分享

void Sift(int a[],int s,int n){ 
    int i=s,j=2*s;
    while(j<=n) {
        //if(j<n && a[j]>a[j+1]) j=j+1;  // small heap get big --> small
        //if(a[i]<=a[j]) break;
        if(j<n && a[j]<a[j+1]) j=j+1;  // big heap get small --> big
        if(a[i]>=a[j]) break;
        else {
            swap(a[i],a[j]);
            i=j;  j=2*j;
        }
    }
}
void HeapSort(int a[],int s,int n){
    for(int i=n/2;i>=1;i--)  Sift(a,i,n);  // 建堆自下而上
    show(a,n);
    for(int i=n;i>1;i--){
        swap(a[1],a[i]);
        Sift(a,1,i-1);
    }
}

堆排序的時間復雜度為O(nlogn),是不穩定的排序算法

二路歸並排序:

最開始是相鄰元素排序。遞歸進行,比較相鄰子集的序列,最後完畢進行排序。
技術分享

const int N=1e3;
int b[N];
void merge(int a[],int sdex,int mdex,int edex){
    int i=sdex,j=mdex+1,k=sdex;
    while(i<=mdex&&j<=edex){
        if(a[i]<a[j]) b[k++]=a[i++];
        else b[k++]=a[j++];
    }
    while(i!=mdex+1) b[k++]=a[i++];
    while(j!=edex+1) b[k++]=a[j++];
    for(i=sdex;i<=edex;i++) a[i]=b[i];
}
void MergeSort(int a[],int sdex,int edex){
    int mdex;
    if(sdex<edex){
        mdex=(sdex+edex)/2;
        MergeSort(a,sdex,mdex);
        MergeSort(a,mdex+1,edex);
        merge(a,sdex,mdex,edex);
    }
}

基礎排序算法