各種排序算法的實現


一.基本概念

1.穩定排序與不穩定排序:

對於A,B兩個鍵值相等的對象,且在排序前,A在B之前,如果排序后A肯定還在B之前,則為穩定排序,如果B可能在A之前,為不穩定排序。

 

2.內排序和外排序:

內排序是指在排序期間數據對象全部存放在內存的排序

外排序是指在排序期間數據對象太多,不能同時存放在內存,必須依照排序過程的要求,不斷在內外存之間移動的排序。

 

二.各種排序算法的實現

1.插入排序

基本思想:插入第i個對象時前i-1個對象已經排好了,將第i個對象插入前i-1個對象的合適地方,使得前i個對象有序。是穩定排序,比較次數和移動次數復雜度都為O(n^2)

void insertSort(int* disorder, int size){
    int temp = 0,i = 0;
    for(int j = 1; j < size; j++){
        temp=disorder[j];
        i = j;
        while(i > 0 && temp < disorder[i-1]){
            disorder[i] = disorder[i-1];
            i--;
        }
        disorder[i] = temp;

    }
}

 

 

2.希爾排序

基本思想:將數列以gap作為間隔分成子序列,分別對子序列進行插入排序,再逐步縮小間隔進行插入排序。shell提出gap取floor(n/2),gap=floor(gap/2).這是一種不穩定的排序。

void shellSort(int* disorder, int size){
    int gap = size / 2;
    int temp = 0, i = 0;
    while(gap > 0){
        for(int g = 0; g < gap; g++){
            for(int j = g + gap; j < size;){
                temp = disorder[j];
                i = j;
                while(i>gap-1 && temp<disorder[i-gap]){
                    disorder[i] = disorder[i-gap];
                    i=i-gap;
                }
                disorder[i]=temp;
                j=j+gap;
            }
        }
        gap=gap/2;
    }
}

 

 

3.起泡排序

基本思想:依次比較key(n)和key(n-1),直到key(2)和key(1),這樣會使最小的對象被起泡到第一個,依次進行起泡,完成排序。是穩定排序,比較次數和移動次數復雜度都為O(n^2)

void bubbleSort(int* disorder, int size){
    int temp=0,modified=0;
    for(int j=1;j<size;j++){
        modified=0;
        for(int i=size-1;i>j-1;i--){
            if(disorder[i]<disorder[i-1]){
                temp = disorder[i];
                disorder[i] = disorder[i-1];
                disorder[i-1]=temp;
                modified++;
            }
        }
        if(modified==0){
            break;
        }
    }
}

 

4.快速排序

基本思想:任取一個對象作為基准,按照關鍵碼的大小,將排序隊列分為左右兩個子序列,小於該對象的都放在左序列,大於該對象的都放在右序列,然后分別對兩個子序列重復上述方法,直到所有對象有序排列。是不穩定排序,比較次數和移動次數復雜度都為O(n*logn)

void quickSort1(int* disorder, int start, int end){
    if(start>=end){
        return;
    }
    int middle=disorder[start];
    int temp=0;
    int pivotpos=start+1,i=start+1;
    for(;i<=end;i++){
        if(disorder[i]<middle){
            if(i!=pivotpos){
                temp=disorder[i];
                disorder[i]=disorder[pivotpos];
                disorder[pivotpos]=temp;
            }
            pivotpos++;
        }
    }
    disorder[start]=disorder[pivotpos-1];
    disorder[pivotpos-1]=middle;
    quickSort1(disorder,start,pivotpos-2);
    quickSort1(disorder,pivotpos,end);
}
void quickSort(int* disorder, int size){
    quickSort1(disorder,0,size-1);
}

 

5.選擇排序

基本思想:每一趟在后面n-i個待排序對象中選出關鍵碼最小的對象,作為有序對象集的第i個對象。不穩定的排序,比較次數為O(n^2),移動次數為O(n)

void selectSort(int* disorder, int size){
    int temp=0,small;
    for(int j=0;j<size-1;j++){
        temp=disorder[size-1];
        small=size-1;
        for(int i=size-2;i>j-1;i--){
            if(disorder[i]<temp){
                temp=disorder[i];
                small=i;
            }
        }
        disorder[small]=disorder[j];
        disorder[j]=temp;
    }
}

 

6.錦標賽排序

基本思想:利用勝者樹來進行選擇排序。穩定的排序,比較次數為O(n*logn).

錦標賽排序雖然節省時間,但是對空間有較大浪費,不推薦

 

7.堆排序

基本思想:利用最大堆,將得到的最大元素依次調整到最后。不穩定的排序,時間復雜度為O(n*logn).

void filterDown(int* disorder, int pos, int size)
{
    int temp = disorder[pos];
    int iPos = pos;
    int iChildPos;
    while(2*iPos+1 < size){
        iChildPos = 2*iPos+1;
        if(iChildPos+1<size && disorder[iChildPos+1] > disorder[iChildPos]){
            iChildPos++;
        }
        if(temp<disorder[iChildPos]){
            disorder[iPos] = disorder[iChildPos];
            iPos = iChildPos;
        }
        else{
            break;
        }
    }
    disorder[iPos] = temp;

}
void heapSort(int* disorder, int size)
{
    for(int i=size/2-1; i>=0; i--){
        filterDown(disorder, i, size);
    }
    int temp;
    for(int i=size-1; i>0; i--){
        temp = disorder[i];
        disorder[i] = disorder[0];
        disorder[0] = temp;
        filterDown(disorder, 0, i);
    }
}

 

8.歸並排序

基本思想:先兩兩排序,再逐步進行歸並。穩定的排序,時間復雜度為O(n*logn).

void merge(int* source,int*dest, int gap, int size){
    int pos1,pos2,end1,end2,destpos=0;
    for(int i=0;i<size;i+=2*gap){
        pos1=i;
        end1=i+gap>size?size:i+gap;
        pos2=i+gap;
        end2=i+2*gap>size?size:i+2*gap;
        while(pos1<end1&&pos2<end2){
            if(source[pos1]<source[pos2]){
                dest[destpos]=source[pos1];
                pos1++;
            }
            else{
                dest[destpos]=source[pos2];
                pos2++;
            }
            destpos++;
        }
        while(pos1<end1){
            dest[destpos++]=source[pos1++];
        }
        while(pos2<end2){
            dest[destpos++]=source[pos2++];
        }

    }
}
void mergeSort(int* disorder, int size){
    int gap=1;
    int* temparr= new int[size];
    while(gap<size){
        merge(disorder, temparr,gap,size);
        gap*=2;
        merge(temparr,disorder,gap,size);
        gap*=2;
    }
    delete[] temparr;
}

 

9.基數排序

基本思想:利用分配和收集的方法進行排序,比如已知數字不超過100,可以按照十位數先進行分配,再分別進行排序后將數字收集起來。

 

三.排序結果的檢驗

對於排序算法,可以用下列的方法來生成一系列的隨機數進行排序,並用isSorted函數來檢驗是否正確的排序了。

bool isSorted(int* disorder, int size){
    for(int i=0;i<size-1;i++){
        if(disorder[i]>disorder[i+1]) return false;
    }
    return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
    const int size=200;
    const int maxnum = 10000;
    int* disorder=new int[size];
    srand((unsigned) time(NULL)); 
    for(int i=0;i<size;i++){
        disorder[i]=rand()%maxnum;    
    }
    mergeSort(disorder,size);
    for(int i=0;i<size;i++){
        cout<<disorder[i]<<endl;
    }
    cout<<isSorted(disorder,size)<<endl;
    return 0;
}

 


免責聲明!

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



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