选择排序
每轮选出最小的元素从头开始放,再在剩下的元素里选出次小的放在次位,循环。
小的往左。
冒泡排序
从右往左,不断交换相邻逆序的元素,在一轮的循环之后,可以让未排序的最大元素上浮到右侧。
大的往右。
插入排序
每步将一个待排序的元素,按其排序码大小插入到前面已经排好序的一组元素的适当位置上去,直到元素全部插入为止。
保证从0到i的元素有序。逐步扩大,保持有序。
希尔排序
又称“分组插入排序”,先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
以不同步长保证等间隔有序,逐渐缩小步长排序。
归并排序
分而治之,将序列递归拆分成多个子序列,再将各个子序列排序后归并叠加,最后归并所有子序列,排序完成。
小组有序。
快速排序
以第一个元素为基准p,左右指针L、R向中间移动扫描,小于基准元素的放到左边,大于基准元素的放到右边,最后将基准元素放到中间,这个位置也就是基准元素的合适位置。此时数据以基准元素为间隔,分为左右两部分(不包括基准元素),然后分别对左右两部分数据分别执行此过程,直到数据不能再分,此时排序完成。
基准分区,左小右大。
堆排序
将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
构造大根堆,替换根节点和尾节点,重新调整成大根堆。
计数排序
要求输入的数据必须是有确定范围的整数。统计每个数出现的次数,然后依次取出。
桶排序
桶排序是计数排序的扩展版本,计数排序可以看成每个桶只存储相同元素,而桶排序每个桶存储一定范围的元素,通过映射函数,将待排序数组中的元素映射到各个对应的桶中,对每个桶中的元素进行排序,最后将非空桶中的元素逐个放入原序列中。
按范围分成有序桶,每个桶内的元素再排序,取出总排。
基数排序
基数排序可以看成是桶排序的扩展,以整数排序为例,主要思想是将整数按位数划分,准备 10 个桶,代表 0 - 9,根据整数个位数字的数值将元素放入对应的桶中,之后按照输入赋值到原序列中,依次对十位、百位等进行同样的操作,最终就完成了排序的操作。
依次按个位、十位、百位排序。
总结
- 内部排序:不依赖外部的空间,直接在数据内部进行排序;
- 外部排序:数据的排序,不能通过内部空间来完成,需要依赖外部空间。
算法分类及适用场景
★ 选择、冒泡、插入、希尔、归并、快速、堆排序都是基于比较的排序。
平均时间复杂度最低O(nlogn)。适用于所有可比较的对象。
★ 计数排序、桶排序、基数排序不是基于比较的排序。
使用空间换时间,某些时候,平均时间复杂度可以低于O(nlogn)。适用于正整数的比较。
稳定性分析
不稳定的排序算法有:快速排序、希尔排序、选择排序、堆排序。
巧记:快『快速排序』、些『希尔排序』、选『选择排序』、堆『堆排序』。
稳定的排序算法有:冒泡排序、插入排序、归并排序、计数排序、桶排序、基数排序。