具体代码请看:NDKPractice项目的datastructure
1. 稳定排序和不稳定排序:
稳定排序概念:通俗地讲就是能保证排序前两个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。
代表:
- 稳定排序:
冒泡
、插入
、归并
- 不稳定排序:
选择
、希尔
、快速排序(可以做到稳定但是比较难)
、堆排序
2. 归并排序
步骤:
- 递归,分治的算法,每次都从中间分隔,然后排序。
- 最后把分别排好序的两个子数组合并,利用一个临时数据作为中转。
思想
:每次循环完毕index在(循环次数+1)前面的数都是排好序的
时间复杂度
:O(N*$\log_2 N$)空间复杂度
:O(N)
每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。
思想:
1 | // 对数组区间 [l,mid] 和 [mid+1,r] 进行归并 |
2. 快速排序
以数组的第一个元素为基准元素(v)进行排序,大于等于v的排在数组右边,小于v的排在数组左边
。最后返回v的下标,再次分为两个数组进行递归操作。
如果>v,和<v 的左右规模接近,那么这个排序就类似归并排序,时间复杂度最优
思想
:每次返回排序后基准元素在数组的下标,也就是说每次只排好了一个数。
时间复杂度
:最差情况:O($n^2$),最好情况(随机快排):O(N*$\log_2 N$)空间复杂度
:最差情况:O(n),最好情况(随机快排):O($\log_2 N$)
1 | // 对数组 arr 区间[l,r] 进行分割操作 |
3. 三路快排
以数组的第一个元素为基准元素(v)进行排序,大于v的排在数组右边,小于v的排在数组左边,剩下的=v在中间
。最后返回=v的数组头尾下标
,再次分为两个数组进行递归操作。
思想
:每次返回排序后,=基准元素v在数组的头尾下标,也就是说每次只排好了所有=v的数
时间复杂度
:最差情况:O($n^2$),最好情况(随机快排):O(N*$\log_2 N$)空间复杂度
:最差情况:O(n),最好情况(随机快排):O($\log_2 N$)
1 | public class Code_04_QuickSort { |
1 | void quickSort3ways_(int arr[], int l, int r) { |