排序基礎算法總結與c++實現

默認都是從小到大排序。有必要註釋。

總結

分類 時間 空間 穩定性
選擇 好、壞、平均都是O(n^2) O(1) 不穩定
插入 平均、壞O(n^2),好O(n) O(1) 穩定
冒泡 平均、壞O(n^2),好O(n) O(1) 穩定
快排 平均、好O(nlogn),壞O(n^2) O(logn) 不穩定
好、壞、平均都是O(nlogn) O(1) 不穩定
歸併 好、壞、平均都是O(nlogn) O(n) 穩定

選擇排序

思想

每次從未排序集合中選出最大的,與未排序集合末端元素交換,直到未排序集合空。

cpp實現

void select_sort(vector<int>& arr){
    for(int len = arr.size(); len > 0; --len){//len表示未排序集合大小
        int max = 0;//max用來記錄未排序集合中最大數的下標
        for(int i = 0; i < len; ++i){
            if(arr[i]>arr[max]) max = i;
        }
        swap(arr[max], arr[len-1]);//將最大數與未排序集合末端元素交換
    }
}

主要優點

數據移動次數。
若某個元素位於正確的最終位置上,則該元素不會被移動。

複雜度分析

一般是說不穩定。(本實現也是。不過,對於數組,把本實現中的內層for循環倒過來,即從後往前找最大,就穩定了…)
空間O(1) 原地操作(優點);
時間O(n^2) 好、壞、平均都一樣。
主要受比較次數制約:n(n-1)/2,與初始狀態無關。
移動(交換)次數最好0次,最多n-1次。
與冒泡比較:n值較小時,選擇排序快於冒泡。
因爲冒泡移動次數爲n^2,一般來說,一次移動(交換)時間長於一次比較時間。

插入排序

思想

將無序區間中的元素依次插入有序區間中的適當位置,直到無序區間長度變爲零。

cpp實現

void insert_sort(vector<int>& arr){
    for(int len = 1; len < arr.size(); ++len){
        int i = 0;
        while(i<len && arr[len]>arr[i]) ++i;
        if(i<len){
            int t = arr[len];
            for(int j = len; j > i; --j) arr[j] = arr[j-1];
            arr[i] = t;
        }
    }
}

快排

常考中的常考,要會手寫,且做到快速、無bug。

思想

白話:“挖洞填數+分治”
(0)首先選擇哨兵元素,將該元素“挖”出來賦給x,並將該位置作爲第一個“洞”(同一時間只會存在一個“洞”)。本實現選擇左界元素爲哨兵。
(1)先從右往左,找比哨兵x小的元素a,將其“挖”出,填入“洞”中,此時a的位置變成了新的“洞”。
(2)再從左往右,找比哨兵x大的元素b,將其“挖”出,填入“洞”中,此時b的位置變成了新的“洞”。
(3)重複執行(1-2)直到左右相遇,此時相遇位置即最後一個“洞”就是哨兵元素x最終有序位置。
(4)將哨兵元素x最終有序位置左右分別進行快排,即分治,直到當前區段長度爲零。

cpp實現

void quick_sort(vector<int>& arr, int l, int h){
    if(l>=h) return;
    int i = l, j = h;
    int x = arr[l];
    while(i<j){
        while(i<j && arr[j]>=x) --j;
        if(i<j) arr[i++] = arr[j];
        while(i<j && arr[i]<=x) ++i;
        if(i<j) arr[j--] = arr[i];
    }
    arr[i] = x;
    quick_sort(arr, l, i-1);
    quick_sort(arr, i+1, h);
}

堆排序

HeapSort堆排序C++實現及相關背景知識

歸併排序

MergeSort歸併排序遞歸、迭代、原地 c++實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章