一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
在计算机的世界里,排序算法有很多,是不是感觉总也记不住?那就对了,因为排序的方法实在太多,基于各种场景,有很多聪明的人想出了各种各样的方法和思想来排序。
排序套路总结
我写了一首关于排序算法的顺口溜,总结几乎所有的排序套路来帮助总结和回忆。如下:
- 冒泡排序两比较
- 每次排序冒最大
- 希尔排序再分组
- 内部有序速度快
- 插入排序最佳N
- 平均还是N平方
- 选择排序先比较
- 最后交换得最大
- 归并排序很简单
- 一刀两断分开算
- 然后再来做合并
- 后序遍历其思想
- 快排主要找基准
- 基准之前是更小
- 基准之后是更大
- 基准找到分两半
- 之后递归直到空
- 前序遍历其思想
- 二叉递归速度快
- 堆排序是全二叉
- 每次交换调堆顶
- 计数排序看数值
- 思想就是值计数
- 一般数组可搞定
- 复杂度是N+K
- K是不同值个数
- 桶排序值范围桶
- 桶内排序减空间
- 基数排序看数位
- 个十百千分别排
- 每位排序也计数
- 复杂度NK好理解
如果有些不好理解的地方,可以看下面的重点解释。
解释和理解
暴力解法
- 冒泡排序两比较
- 冒泡排序每一轮两两比较数组,如果不是有序的就交换
- 每次排序冒最大
- 每一轮之后得到最大值
- 排序N轮之后,冒泡排序完成
- 希尔排序再分组
- 希尔排序是在冒泡排序的基础上再分组冒泡
- 内部有序速度快
- 当是更大范围的冒泡排序的时候,内部已经有顺序了
- 插入排序最佳N
- 插入排序将数组的前面部分认为是从小到大的有序数列,再将后面的数依次插入到这个数列中。如果数组本身就是有序的,则复杂度是O(n),这是最好的情况。平均复杂度还是n的平方。
- 平均还是N平方
- 选择排序先比较
- 选择排序的思想是每轮选择出来一个最大的,并和最后一个元素交换。
- 最后交换得最大
二分思想
- 归并排序很简单
- 一刀两断分开排
- 然后再来做合并
- 后序遍历其思想
- 归并排序是一个非常有用的排序算法,基本思想是将数组分为两半分别排序,再合并。是一种二叉树后续遍历的思想。
- 快排主要找基准
- 基准之前是更小
- 基准之后是更大
- 基准找到分两半
- 之后递归直到空
- 前序遍历其思想
- 快排的算法实现看起来可能有点难,但是理解其基本思想是二叉树的前序遍历就很简单了。在遍历排序之前,先找到一个基准(比如最后一个元素),通过简单的原地比较交换,大于基准值的元素放到基准后面,反之相反。通过基准将数组分为两半了,再分别对前后范围分别递归进行这样的排序。
- 二叉递归速度快
- 归并排序和快速排序都采用了二叉树递归的思想,排序时间复杂度是NlogN。归并排序需要的额外空间复杂度是N。
- 堆排序是全二叉
- 堆排序的思想是将数组认为是一颗完全二叉树,利用完全二叉树孩子节点和父节点的索引关系来快速调整排序。
- 每次交换调堆顶
- 初始化,从下到上调整每个非叶子节点,使得节点的值大于每个叶子节点。得到一颗最大堆。交换堆顶元素和数组最后一个元素的值。再调整堆顶。每次调整的过程只需要将堆顶元素依次和叶子节点的最大值交换就可以调整出一颗大顶堆出来。
计数思想
- 计数排序看数值
- 思想就是值计数
- 计数排序有着和前面不一样的排序思想,完全不利用比较的思想。主要看要排序的值范围。如果排序的数值范围较小,时空复杂度会表现良好。扫描一次源数组,用一个大小为k的数组存储值的个数。再通过这个计数数组便可以很方便的得到排好序的数组了。
- 一般数组可搞定
- 复杂度是N+K
- K是不同值个数
- 桶排序值范围桶
- 桶内排序减空间
- 桶排序是计数排序的扩展,每个桶存储一个值的范围,比如5到10,再对每个桶分别排序。通过调整值范围,桶排序在计数排序的基础上,可以更好的权衡时间复杂度和空间复杂度。
- 基数排序看数位
- 基数排序一般也是为了扩展计数排序,但是用数值位的方式去扩展。先对个位采用计数排序排序,这样计数的数组大小为10就可以满足要求了,再依次对十百等位进行排序,到最后一位则排序结束。
- 个十百千分别排
- 每位排序也计数
- 复杂度NK好理解
- 基数排序的复杂度是Nk,k为10