十大經典排序算法整理彙總(附代碼)

關注公衆號【算法碼上來】,每日算法乾貨立刻就來!

前言

本文整理並總結了十大經典的排序算法(冒泡排序、選擇排序、插入排序、快速排序、歸併排序、希爾排序、計數排序、基數排序、桶排序、堆排序)的時間複雜度、空間複雜度等性質。c++

本文並不會詳細講解每種排序算法的原理,網上有不少很好的教程,你們能夠本身去搜了看。算法

最後我還親自手寫了十種排序算法的 c++ 代碼,你們能夠用來經過 LeetCode 912. 排序數組 這道題。shell

性質彙總

若是發現表中有錯誤,請留言告知。
算法 最好 最壞 平均 空間 穩定性 是否基於比較
冒泡排序 $O(n)$ $O(n^2)$ $O(n^2)$ $O(1)$ $\checkmark$ $\checkmark$
選擇排序 $O(n^2)$ $O(n^2)$ $O(n^2)$ $O(1)$ $\times$ $\checkmark$
插入排序 $O(n)$ $O(n^2)$ $O(n^2)$ $O(1)$ $\checkmark$ $\checkmark$
快速排序 $O(n\log n)$ $O(n^2)$ $O(n\log n)$ $O(\log n)$~$O(n)$ $\times$ $\checkmark$
歸併排序 $O(n\log n)$ $O(n\log n)$ $O(n\log n)$ $O(n)$ $\checkmark$ $\checkmark$
希爾排序 $O(n^{1.3})$ $O(n^2)$ $O(n\log n)$~$O(n^2)$ $O(1)$ $\times$ $\checkmark$
計數排序 $O(n+k)$ $O(n+k)$ $O(n+k)$ $O(n+k)$ $\checkmark$ $\times$
基數排序 $O(nk)$ $O(nk)$ $O(nk)$ $O(n+k)$ $\checkmark$ $\times$
桶排序 $O(n)$ $O(n)$ $O(n)$ $O(n+m)$ $\checkmark$ $\times$
堆排序 $O(n\log n)$ $O(n\log n)$ $O(n\log n)$ $O(1)$ $\times$ $\checkmark$
若是表格顯示有問題的話,還能夠直接看下面的彙總圖:

十大經典排序算法性質彙總

維基百科

我以爲仍是英文維基百科講的比較詳細、嚴謹。若是你們看的比較累的話,能夠本身百度搜索相應的教程。數組

冒泡排序
https://en.wikipedia.org/wiki/Bubble_sort工具

選擇排序
https://en.wikipedia.org/wiki/Selection_sortui

插入排序
https://en.wikipedia.org/wiki/Insertion_sortspa

快速排序
https://en.wikipedia.org/wiki/Quicksortcode

歸併排序
https://en.wikipedia.org/wiki/Merge_sort排序

希爾排序
https://en.wikipedia.org/wiki/Shellsort教程

計數排序
https://en.wikipedia.org/wiki/Counting_sort

基數排序
https://en.wikipedia.org/wiki/Radix_sort

桶排序
https://en.wikipedia.org/wiki/Bucket_sort

堆排序
https://en.wikipedia.org/wiki/Heapsort

代碼實現

全部的排序算法接口都是相同的,也就是 vector<int> xxxSort(vector<int>& nums) 。只須要你傳入一個 vector<int> 類型的數組,就能返回排序後的結果。

運行下來能夠發現,桶排序速度是比較快的。而冒泡排序、選擇排序和插入排序由於時間複雜度過高沒法經過本題,基數排序由於沒法處理負數也不能經過本題。

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        return quickSort(nums);
    }

    // 冒泡排序(超時)
    vector<int> bubbleSort(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            for (int j = n-2; j >= i; --j) {
                if (nums[j] > nums[j+1]) {
                    swap(nums[j], nums[j+1]);
                }
            }
        }
        return nums;
    }

    // 選擇排序(超時)
    vector<int> selectSort(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            int idx = i;
            for (int j = i; j < n; ++j) {
                if (nums[j] < nums[idx]) {
                    idx = j;
                }
            }
            swap(nums[i], nums[idx]);
        }
        return nums;
    }

    // 插入排序(超時)
    vector<int> insertSort(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            for (int j = i; j > 0 && nums[j] < nums[j-1]; --j) {
                swap(nums[j], nums[j-1]);
            }
        }
        return nums;
    }

    // 快速排序(24 ms)
    void qSort(vector<int>& nums, int l, int r) {
        if (l >= r) return;
        int m = l;
        for (int i = l; i < r; ++i) {
            if (nums[i] < nums[r]) {
                swap(nums[m++], nums[i]);
            }
        }
        swap(nums[m], nums[r]);
        qSort(nums, l, m-1);
        qSort(nums, m+1, r);
    }

    vector<int> quickSort(vector<int>& nums) {
        int n = nums.size();
        qSort(nums, 0, n-1);
        return nums;
    }

    // 歸併排序(192 ms)
    vector<int> mSort(vector<int>& nums, int l, int r) {
        if (l >= r) return {nums[l]};
        int m = l+(r-l)/2;
        vector<int> lnums = mSort(nums, l, m);
        vector<int> rnums = mSort(nums, m+1, r);
        vector<int> res;
        int i = 0, j = 0;
        while (i <= m-l && j <= r-m-1) {
            if (lnums[i] < rnums[j]) {
                res.push_back(lnums[i++]);
            } else {
                res.push_back(rnums[j++]);
            }
        }
        while (i <= m-l) {
            res.push_back(lnums[i++]);
        }
        while (j <= r-m-1) {
            res.push_back(rnums[j++]);
        }
        return res;
    }

    vector<int> mergeSort(vector<int>& nums) {
        int n = nums.size();
        nums = mSort(nums, 0, n-1);
        return nums;
    }

    // 歸併排序 + 非遞歸(80 ms)
    vector<int> mergeSortNR(vector<int>& nums) {
        int n = nums.size();
        for (int len = 1; len < n; len <<= 1) {
            for (int l = 0; l < n-len; l += 2*len) {
                int m = l+len-1;
                int r = min(n-1, l+2*len-1);
                vector<int> res;
                int i = l, j = m+1;
                while (i <= m && j <= r) {
                    if (nums[i] < nums[j]) {
                        res.push_back(nums[i++]);
                    } else {
                        res.push_back(nums[j++]);
                    }
                }
                while (i <= m) {
                    res.push_back(nums[i++]);
                }
                while (j <= r) {
                    res.push_back(nums[j++]);
                }
                for (int i = l; i <= r; ++i) {
                    nums[i] = res[i-l];
                }
            }
        }
        return nums;
    }

    // 希爾排序(40 ms)
    vector<int> shellSort(vector<int>& nums) {
        int n = nums.size();
        for (int gap = n/2; gap > 0; gap /= 2) {
            for (int i = gap; i < n; ++i) {
                for (int j = i; j-gap >= 0 && nums[j-gap] > nums[j]; j -= gap) {
                    swap(nums[j-gap], nums[j]);
                }
            }
        }
        return nums;
    }

    // 計數排序(32 ms)
    vector<int> countSort(vector<int>& nums) {
        int n = nums.size();
        if (!n) return {};
        int minv = *min_element(nums.begin(), nums.end());
        int maxv = *max_element(nums.begin(), nums.end());
        int m = maxv-minv+1;
        vector<int> count(m, 0);
        for (int i = 0; i < n; ++i) {
            count[nums[i]-minv]++;
        }
        vector<int> res;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < count[i]; ++j) {
                res.push_back(i+minv);
            }
        }
        return res;
    }

    // 基數排序(不適用於負數)
    vector<int> radixSort(vector<int>& nums) {
        int n = nums.size();
        int maxv = *max_element(nums.begin(), nums.end());
        int maxd = 0;
        while (maxv > 0) {
            maxv /= 10;
            maxd++;
        }
        vector<int> count(10, 0), rank(n, 0);
        int base = 1;
        while (maxd > 0) {
            count.assign(10, 0);
            for (int i = 0; i < n; ++i) {
                count[(nums[i]/base)%10]++;
            }
            for (int i = 1; i < 10; ++i) {
                count[i] += count[i-1];
            }
            for (int i = n-1; i >= 0; --i) {
                rank[--count[(nums[i]/base)%10]] = nums[i];
            }
            for (int i = 0; i < n; ++i) {
                nums[i] = rank[i];
            }
            maxd--;
            base *= 10;
        }
        return nums;
    }

    // 桶排序 (20 ms)
    vector<int> bucketSort(vector<int>& nums) {
        int n = nums.size();
        int maxv = *max_element(nums.begin(), nums.end());
        int minv = *min_element(nums.begin(), nums.end());
        int bs = 1000;
        int m = (maxv-minv)/bs+1;
        vector<vector<int> > bucket(m);
        for (int i = 0; i < n; ++i) {
            bucket[(nums[i]-minv)/bs].push_back(nums[i]);
        }
        int idx = 0;
        for (int i = 0; i < m; ++i) {
            int sz = bucket[i].size();
            bucket[i] = quickSort(bucket[i]);
            for (int j = 0; j < sz; ++j) {
                nums[idx++] = bucket[i][j];
            }
        }
        return nums;
    }

    // 堆排序(32 ms)
    void adjust(vector<int>& nums, int p, int s) {
        while (2*p+1 < s) {
            int c1 = 2*p+1;
            int c2 = 2*p+2;
            int c = (c2<s && nums[c2]>nums[c1]) ? c2 : c1;
            if (nums[c] > nums[p]) swap(nums[c], nums[p]);
            else break;
            p = c;
        }
    }

    vector<int> heapSort(vector<int>& nums) {
        int n = nums.size();
        for (int i = n/2-1; i >= 0; --i) {
            adjust(nums, i, n);
        }
        for (int i = n-1; i > 0; --i) {
            swap(nums[0], nums[i]);
            adjust(nums, 0, i);
        }
        return nums;
    }
};
本文由博客羣發一文多發等運營工具平臺 OpenWrite 發佈
相關文章
相關標籤/搜索