排序 是将一组乱的数据按一定准则排好顺序。
一般按照时间复杂度大概分为三类:
一: O(n^2) 冒泡排序,选择排序,插入排序,希尔排序(性能优于O(n^2),差于O(nlog));
二: O(nlogn) 快速排序,归并排序,堆排序;
三: O(n) 基数排序,桶排序,计数排序。
根据其稳定性:稳定排序和不稳定排序。
稳定性排序:值相同的两个元素排序完,它两的相对位置不变。如下图:黄色的 6 和 白色的 6 值一样排完序后,黄色 6 仍在白色 6 的前面则是稳定排序。
稳定排序:冒泡排序,插入排序,归并排序,计数排序,桶排序,基数排序;
不稳定排序:选择排序,希尔排序,快速排序,堆排序;
1.冒泡排序
定义:反复的走访要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来,这个工作反复的进行直至没有元素需要交换。
由于这篇是排序总结,冒泡的详解大家可以看一下我之前写的冒泡的文章: 冒泡排序的详解和优化。
冒泡排序的时间复杂度是O(n^2),空间复杂度是O(1),稳定性排序。
鸡尾酒排序:是冒泡排序的一个版本,是从头比较到尾部后又从尾部比较回来。适用于绝大多数已经排好序的情况。具体实现:鸡尾酒排序详解
2. 选择排序
定义:冒泡排序的一种优化,每次循环找到剩下数列元素中最小(大)的数交换到剩下元素数列的最前面。
优点:它相对与冒泡排序大大减少了交换次数(减少好多到内存中读写,减少cpu工作量,提高性能),只是剩下元素最小(大)的数和剩下元素中最前面的数交换。
具体的实现:选择排序详解
时间复杂度也是O(n^2),空间复杂度O(1),不稳定排序。
3. 插入排序:
定义:对于未排序的数据,在已排好的序列中从后往前扫描,找到合适的位置并插入。
优点:对于大部分元素是有序的,这种方法十分划算。
时间复杂度最坏O(n^2),最好O(n);空间复杂度 O(1),稳定排序。
具体详解:直接插入排序详解
二分插入排序:一种插入排序,在插入有序数列时,使用二分法查找位置,具体实现大家自己实现一下。
4. 希尔排序:
定义:又叫缩小量排序,插入排序的优化版。把待排序的数组按一定数量的分组,对每组使用直接插入排序算法排序;然后再缩小数量继续分组排序,直至整个数组分成一组,排序完成。
具体详情:希尔算法详解
时间复杂度小于O(n^2),空间复杂度O(1),不稳定排序。
优点:对于大部分元素乱的时候,插入排序的优化。
5. 归并排序:
定义:利用递归与分治技术将数据序列划分成为越来越小的半子表,在对半子表排序后,再用递归方法将排好的半子表合成为越来越大的有序序列。
具体实现:归并详解
时间复杂度O(nlogn) 空间复杂度O(n),稳定排序。
6. 快速排序:
定义:冒泡排序的改进,分治的典型。选择一个基数,分别从数组的左边和右边与基数比较,大的放在基数的右边,小的放在基数左边。然后,再在基数的左右选择基数排序直至最后数组排序好。
具体实现:快速排序详解
时间复杂O(nlogn),空间复杂O(logn),不稳定排序。
7.堆排序:
定义:利用完全二叉树的特性,实现排序。每次取出最大(小)堆的根节点进行排序。
具体实现:堆排序详解
想直接获取最大(小)值: 优先队列详解
时间复杂度O(nlogn),空间复杂度O(1),不稳定排序。
8. 计数排序:
定义:用一个数组从小到大记录数组中相应大小数的次数,然后遍历这个数组记录的次数排序。
具体实现:计数排序详解
时间复杂度O(n+k),空间复杂度O(k)稳定排序。
特点:1.只适合整数排序,2.对数据跨度大的不适合,3.不进行比较的排序算法
9. 桶排序:
定义:利用某种函数映射关系将数据分布到有限数量的桶中,每个桶分别排序。
具体实现:桶排序详解
时间复杂度O(n+k),空间复杂度O(n+k)稳定排序。
特点:减少了几乎所有的比较。
10.基数排序:
定义:按照从右往左的顺序,依次将每一位都当作一次关键字,然后按照该关键字对数组排序,同时每一轮排序都基于上轮排序后的结果;当将所有的位排序完之后,整个数组都达到了有序状态。
基数是什么呢?对于十进制整数,每一位都可能是0~9其中的某一个,总共10种可能,那10就是它的基数。同理二进制数字基数为2,字符串如果使用的是8位的扩展ASCII字符集,那么基数是256.
具体实现:基数排序详解
时间复杂度O(n+k),空间复杂度O(n+k)稳定排序。
总结:
1. 时间复杂度由小到大:O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)
2. 冒泡,选择,插入排序需要两个for循环,每次只关注一个元素,平均时间复杂度O(n^2)(一遍找元素O(n), 一遍找位置O(n));
快速,归并,堆基于分治思想,log以2为底,平均时间复杂度O(nlogn) (一遍找元素O(n),一遍找位置O(logn));
希尔排序依赖增量序列的性质,但目前没有最好的。例如希尔增量序列时间复杂度为O(n^2),Hibbard增量序列时间复杂度 为O(n^(1/2))。
3. 从平均时间来看,快速排序的效率最高,
快速排序的平局时间复杂度是O(nlogn),虽然归并也是O(nlogn)。但是,快速中的 n 会比归并中的小很多;
堆排序的平均时间复杂度也是O(nlogn),但是堆排序每次取出最大(小)值 ,都会进行堆重排,消耗很多性能。
4. 最后ps上总结表,拿走不谢: