快速排序 Vs. 归并排序 Vs. 堆排序——谁才是最强的排序算法
知乎上有一个问题是这样的:
堆排序是渐进最优的比较排序算法,达到了O(nlgn)这一下界,而快排有一定的可能性会产生最坏划分,时间复杂度可能为O(n^2),那为什么快排在实际使用中通常优于堆排序?
昨天刚好写了一篇关于快排优化的文章,今天再多做一个比较吧。首先先看一个排序算法图:
| 排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 | 
|---|---|---|---|---|---|
| 冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 | 
| 简单选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 稳定 | 
| 直接插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 | 
| 希尔排序 | O(nlogn)~O(n^2) | O(n^1.3) | O(n^2) | O(1) | 不稳定 | 
| 堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 | 
| 归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 | 
| 快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn)~O(n) | 不稳定 | 
可以看到,到达nlogn级别的排序算法,一共有三种,分别是堆排序,归并排序以及快速排序,其中只有归并排序最稳定。那么,为什么要说快速排序的平均情况是最快的呢?
实际上在算法分析中,大O的作用是给出一个规模的下界,而不是增长数量的下界。因此,算法复杂度一样只是说明随着数据量的增加,算法时间代价增长的趋势相同,并不是执行的时间就一样,这里面有很多常量参数的差别,比如在公式里各个排序算法的前面都省略了一个c,这个c对于堆排序来说是100,可能对于快速排序来说就是10,但因为是常数级所以不影响大O。
另外,即使是同样的算法,不同的人写的代码,不同的应用场景下执行时间也可能差别很大。下面是一个测试数据:
测试的平均排序时间:数据是随机整数,时间单位是s
数据规模    快速排序       归并排序        希尔排序        堆排序
1000万       0.75           1.22          1.77          3.57
5000万       3.78           6.29          9.48         26.54
1亿          7.65          13.06         18.79         61.31
堆排序每次取一个最大值和堆底部的数据交换,重新筛选堆,把堆顶的X调整到位,有很大可能是依旧调整到堆的底部(堆的底部X显然是比较小的数,才会在底部),然后再次和堆顶最大值交换,再调整下来,可以说堆排序做了许多无用功。
总结起来就是,快排的最坏时间虽然复杂度高,但是在统计意义上,这种数据出现的概率极小,而堆排序过程里的交换跟快排过程里的交换虽然都是常量时间,但是常量时间差很多。
快速排序 Vs. 归并排序 Vs. 堆排序——谁才是最强的排序算法的更多相关文章
- 选择排序、快速排序、归并排序、堆排序、快速排序实现及Sort()函数使用
		1.问题来源 在刷题是遇到字符串相关问题中使用 strcmp()函数. 在函数比较过程中有使用 排序函数 Sort(beg,end,comp),其中comp这一项理解不是很彻底. #include & ... 
- Javascript中的冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序  算法性能分析
		阿里面试中有一道题是这样的: 请用JavaScript语言实现 sort 排序函数,要求:sort([5, 100, 6, 3, -12]) // 返回 [-12, 3, 5, 6, 100],如果你 ... 
- 数据结构之排序技术:快速排序、归并排序、堆排序(C++版)
		快速排序 #include <iostream> using namespace std; void swap(int num[], int i, int j) { int temp = ... 
- 数据结构(5) 第五天 快速排序、归并排序、堆排序、高级数据结构介绍:平衡二叉树、红黑树、B/B+树
		01 上次课程回顾 希尔排序 又叫减少增量排序 increasement = increasement / 3 + 1 02 快速排序思想 思想: 分治法 + 挖坑填数 分治法: 大问题分解成各个小问 ... 
- Java实现单链表的快速排序和归并排序
		本文描述了LeetCode 148题 sort-list 的解法. 题目描述如下: Sort a linked list in O(n log n) time using constant space ... 
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
		归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ... 
- 排序算法之堆排序(Heapsort)解析
		一.堆排序的优缺点(pros and cons) (还是简单的说说这个,毕竟没有必要浪费时间去理解一个糟糕的的算法) 优点: 堆排序的效率与快排.归并相同,都达到了基于比较的排序算法效率的峰值(时间复 ... 
- Java学习笔记——排序算法之快速排序
		会当凌绝顶,一览众山小. --望岳 如果说有哪个排序算法不能不会,那就是快速排序(Quick Sort)了 快速排序简单而高效,是最适合学习的进阶排序算法. 直接上代码: public class Q ... 
- javascript高级排序算法之快速排序(快排)
		javascript高级排序算法之快速排序(快排)我们之前讨论了javascript基本排序算法 冒泡排序 选择排序 插入排序 简单复习: 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换 ... 
随机推荐
- [TimLinux] myblog 首页创建
			1. 设计 2. 结构 3. 实现 templates/common/layout.html: <!DOCTYPE html> <html lang="zh"&g ... 
- JavaEE基础(04):会话跟踪技术,Session和Cookie详解
			本文源码:GitHub·点这里 || GitEE·点这里 一.会话跟踪 1.场景描述 比如登录某个购物网站,身份识别成功后,在网站下单,支付 等操作,这些操作中当前登录用户信息必须是共享的,这样这些操 ... 
- 带你快速了解Java锁中的公平锁与非公平锁
			前言 Java语言中有许多原生线程安全的数据结构,比如ArrayBlockingQueue.CopyOnWriteArrayList.LinkedBlockingQueue,它们线程安全的实现方式并非 ... 
- item()方法遍历字典
			Python字典的遍历方法有好几种,其中一种是for...in,这个我就不说明,在Python了几乎随处都可见for...in.下面说的这种遍历方式是item()方法. item() item()方法 ... 
- 这几种JavaScript语法不要轻易使用,容易出事
			文章目录 12种不宜使用的JavaScript语法 1. == 2. with 3. eval 4. continue 5. switch 贯穿 6. 单行的块结构 7. ++和-- 8. 位运算符 ... 
- 蝉知CMS5.6反射型XSS审计复现
			0x00 源起 最近在深入学习反射XSS时遇到蝉知CMS5.6反射型XSS这个案列,乍一看网上的漏洞介绍少之又少,也没有详细的审计复现流程.虽然是17年的漏洞了,不巧本人正是一个喜欢钻研的人.这个CM ... 
- CentOS7自动化安装PXE方案
			目的 无人值守批量安装CentOS7 安装条件 一台带有PXE协议支持NIC的待安装主机 一台存放安装文件的服务器,如NFS,HTTP或FTP服务器 Kickstart 生成的配置文件(ks.cfg) ... 
- Gradle  自定义插件
			使用版本 5.6.2 插件被用来封装构建逻辑和一些通用配置.将可重复使用的构建逻辑和默认约定封装到插件里,以便于其他项目使用. 你可以使用你喜欢的语言开发插件,但是最终是要编译成字节码在 JVM 运行 ... 
- Mysql相关知识总结-持续更新~~~
			2019-12-11对varchar类型排序问题的解决 在mysql默认order by 只对数字与日期类型可以排序,但对于varchar字符型类型排序好像没有用了,下面我来给各位同学介绍varcha ... 
- Newifi D1或 D2在Openwrt中,启用硬件NAT,启用BBR
			Newifi D1或 D2在Openwrt中,启用硬件NAT,启用BBR 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-09-27. 启用 mt7621的硬件nat (Newifi ... 
