十大经典排序算法整理汇总(附代码)

简介: 十大经典排序算法整理汇总(附代码)

前言

本文整理并总结了十大经典的排序算法(冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、计数排序、基数排序、桶排序、堆排序)的时间复杂度、空间复杂度等性质。

本文并不会详细讲解每种排序算法的原理,网上有很多很好的教程,大家可以自己去搜了看。

最后我还亲自手写了十种排序算法的 c++ 代码,大家可以用来通过 LeetCode 912. 排序数组[1] 这道题。

性质汇总

如果发现图中有错误,请留言告知。

十大经典排序算法性质汇总

维基百科

我觉得还是英文维基百科讲的比较详细、严谨。如果大家看的比较累的话,可以自己百度搜索相应的教程。

冒泡排序

https://en.wikipedia.org/wiki/Bubble_sort

选择排序

https://en.wikipedia.org/wiki/Selection_sort

插入排序

https://en.wikipedia.org/wiki/Insertion_sort

快速排序

https://en.wikipedia.org/wiki/Quicksort

归并排序

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;
    }
};
相关文章
|
算法 搜索推荐 Java
acwing算法基础课学习笔记(第一章:基础算法)
acwing基础算法基础课学习笔记。算法包括:快速排序、归并排序、二分、高精度、前缀和与差分、双指针算法、位运算、离散化、区间合并。
304 0
|
机器学习/深度学习 存储 人工智能
AcWing算法基础课笔记 第一章 基础算法
​编辑快速排序算法模板 —— 模板题 AcWing 785. 快速排序 归并排序算法模板 —— 模板题 AcWing 787. 归并排序 整数二分算法模板 —— 模板题 AcWing 789. 数的范围 浮点数二分算法模板 —— 模板题 AcWing 790. 数的三次方根 高精度加法 —— 模板题 AcWing 791. 高精度加法 高精度减法 —— 模板题 AcWing 792. 高精度减法 高精度乘低精度 —— 模板题 AcWing 793. 高精度乘法 高精度除以低精度 —— 模板题 AcWing 794. 高精度除法 一维前缀和 —— 模板题 AcWing 795.
328 0
|
机器学习/深度学习 并行计算 测试技术
百度飞桨学院小白逆袭大神第四天(笔记+解题思路)
百度飞桨学院小白逆袭大神第四天(笔记+解题思路)
163 0
百度飞桨学院小白逆袭大神第四天(笔记+解题思路)
|
搜索推荐 算法
九大经典排序算法(王道考研排序算法整理)
九大经典排序算法(王道考研排序算法整理)
180 0
九大经典排序算法(王道考研排序算法整理)
|
算法 搜索推荐 Shell
【数据结构与算法】之十大经典排序算法(上)
【数据结构与算法】之十大经典排序算法(上)
125 0
【数据结构与算法】之十大经典排序算法(上)
|
存储 移动开发 算法
【数据结构与算法】之十大经典排序算法(下)
【数据结构与算法】之十大经典排序算法(下)
|
算法
《算法基础课我的最爱》==》第一课(一)
《算法基础课我的最爱》==》第一课
82 0
|
算法
《算法基础课我的最爱》==》第一课(二)
《算法基础课我的最爱》==》第一课
78 0
|
算法
《算法基础课我的最爱》==》第一课(三)
《算法基础课我的最爱》==》第一课
75 0
uiu
|
存储 移动开发 算法
十大经典排序算法的总结(下)
十大经典排序算法的总结(下)
uiu
90 0