前言

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

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

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

性质汇总

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

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

维基百科

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

冒泡排序
https:// en.wikipedia.org/wiki/B ubble_sort

选择排序
https:// en.wikipedia.org/wiki/S election_sort

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

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

归并排序
https:// en.wikipedia.org/wiki/M erge_sort

希尔排序
https:// en.wikipedia.org/wiki/S hellsort

计数排序
https:// en.wikipedia.org/wiki/C ounting_sort

基数排序
https:// en.wikipedia.org/wiki/R adix_sort

桶排序
https:// en.wikipedia.org/wiki/B ucket_sort

堆排序
https:// en.wikipedia.org/wiki/H eapsort

代码实现

所有的排序算法接口都是相同的,也就是 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;}
};

参考资料

[1]

LeetCode 912. 排序数组: https://leetcode-cn.com/problems/sort-an-array/

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

  1. 十大经典排序算法小结(附源码和菜鸟版注释)

    序 在十大经典排序算法(动画演示)这篇博客的指导下,博主一点一点码出了十大排序算法,并写了菜鸟级注释,源码戳这里,下面记录一下自己的总结,基本上是从注释搬来的. 排序算法主要分两类,一类是比较类排序, ...

  2. java array 元素的位置_数据结构与算法:动态图解十大经典排序算法(含JAVA代码实现)...

    点击上方"JAVA",星标公众号 重磅干货,第一时间送达 本文将采取动态图+文字描述+正确的java代码实现来讲解以下十大排序算法: 冒泡排序 选择排序 插入排序 希尔排序 归并排 ...

  3. 买什么数据结构与算法,这里有:动态图解十大经典排序算法(含JAVA代码实现)

    上篇的动图数据结构反响不错,这次来个动图排序算法大全.数据结构与算法,齐了. 几张动态图捋清Java常用数据结构及其设计原理 本文将采取动态图+文字描述+正确的java代码实现来讲解以下十大排序算法: ...

  4. c语言代码先来先服务算法_C语言十大经典排序算法(动态演示+代码,值得收藏)...

    以前也零零碎碎发过一些排序算法,但排版都不太好,又重新整理一次,排序算法是数据结构的重要部分,系统地学习很有必要. 时间.空间复杂度比较 排序算法 平均时间复杂度 最差时间复杂度 空间复杂度 数据对象 ...

  5. 十大经典排序算法(图解与代码)——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序(Python and Java)

    排序 重新排列表中的元素,使表中的元素按照关键字递增或者递减 内部排序: 指在排序期间,元素全部存放在内存中的排序 外部排序: 指在排序期间元素无法全部同时存放在内存中,必须在排序的过程中根据要求不断 ...

  6. java分治法求数列的最大子段和_Java十大经典排序算法动画解析和 代码实现

    排序算法是<数据结构与算法>中最基本的算法之一. 排序算法可以分为内部排序和外部排序. 内部排序是数据记录在内存中进行排序. 而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排 ...

  7. 十大经典排序算法之堆排序(Java代码实现)

    算法原理 堆排序(Heap Sort)是指利用堆这种数据结构所设计的一种排序算法.堆积是一个近视完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点.堆排序可以说 ...

  8. 按复杂度有效性递减排序_十大经典排序算法:python源码实现,通俗深入讲解

    概述 提示:本文上万字,陆陆续续疏理知识点加测试代码,耗时近一个月.阅读时长40分钟左右. 本文将十大经典排序算法进行汇总,从源码实现.复杂度.稳定性进行分析,并对每种排序的特性进行点评.对典型算法, ...

  9. 终于,把十大经典排序算法汇总了!(Java实现版)

    转载自  终于,把十大经典排序算法汇总了!(Java实现版) 最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在" ...

  10. 11月14日云栖精选夜读 | 动画+原理+代码,解读十大经典排序算法

    排序算法是<数据结构与算法>中最基本的算法之一. 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过 ...

最新文章

  1. TCP超时与重传机制与拥塞避免
  2. python开发需要掌握哪些知识-Python基础学习需要掌握哪些知识
  3. while((ch=getchar())!=EOFch != '\n');消除非法输入
  4. 最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇
  5. iOS APP如何跳转小程序?友盟分享到微信的时候调不起微信是什么原因?
  6. 飞控硬件在环之GPS模拟器
  7. PR常用的效果和转场,视频防抖、宽银幕效果、设置默认效果
  8. 视频格式基础知识:让你了解MKV、MP4、H.265、码率、色深等等
  9. python 小程序——快递分拣程序
  10. linux 卸载skype,在Ubuntu 20.04系统下使用snap和apt安装Skype的方法
  11. 【xinfanqie】熟知针式与喷墨打印机之间的区别
  12. 图片提取文字怎么操作
  13. 分布式系列_MQ_01_MQ简介
  14. 视觉检测零件同轴度 测试零件同轴度,检测是否同心圆
  15. ngrok使用/踩坑分析-http代理
  16. ssh 使用新法:公网(合法 ip)用户访问内网(私有 ip)服务器(http,ftp,sshd,cvs...),内网的朋友不妨一看。
  17. Android版本对照
  18. BEV感知的开源数据集分享
  19. -1和255有什么区别?
  20. MATLAB 画一株会害羞的含羞草

热门文章

  1. new 动态分配数组空间 .xml
  2. Tomcat部署记事
  3. linux中文显示和输入
  4. Silverlight 2 跨域访问控件与WebService的资料整理
  5. 【百度地图API】情人节求爱大作战——添加标注功能
  6. 中国分省市地图导航-SVG格式(基于Raphaël)
  7. PaddlePaddle(7)—— 项目全流程实战:公共场所吸烟检测与EasyEdge部署
  8. ZeroC Ice介绍与简单demo构建
  9. 宏定义(#ifndef+#define+#endif)的作用
  10. 一个java内存泄漏的排查案例