当前位置:   article > 正文

排序算法 下

排序算法 下

目录

1.快速排序

2.归并排序

3.计数排序


1.快速排序

快速排序是Hoare在1962年提出的一种二叉树结构的交换排序的方法,采用了递归的思想

思想:任取待排序的元素序列中的某元素作为基准值,按照原来的顺序将序列分为两个子序列,

左子序列中的所有元素均小于基准直,右子树的所有序列中的元素均大于基准直,然后左右子序列重复该过程,直到所有元素都排在相应的位置上。

先写出大致的框架,与二叉树的前序遍历非常之像,写递归框架可以照着二叉树前序遍历写出来,

后续只要分析如何按照基准直对区间中的数据划分即可

  1. public static void QuickSort(int[] array,int start,int end){
  2. //递归结束的条件
  3. if(start >= end){
  4. return;
  5. }
  6. //如果子区间的数据越来越少了,直接采用 范围插入排序 更快
  7. if(end-start+1 < 10){
  8. insertSort(array,start,end);
  9. return;
  10. }
  11. //三数取中原因:
  12. //如果这个序列是接近有序的,1 2 3 4 5 6 7 8 9 11 10
  13. //基准值一般选取最左侧的数据 1,那么每次递归1的左侧没有子序列,只有右侧
  14. //所以会大大提高时间复杂度,
  15. //那么就取最左,最有,最中三个数据的中位数,
  16. //将中位数与第一个数交换,这样返回的基准直就不是1了,而是与1交换的数
  17. int index = midTreeNum(array,start,end);
  18. swap(array,start,index);
  19. //寻找基准直位置的下标
  20. //该方法有很多种,等下面我们一一介绍
  21. int par = paririon(array,start,end);
  22. //按照基准直,将其左右两个子区间进行排序
  23. QuickSort(array,start,par-1);
  24. QuickSort(array,par+1,end);
  25. }
  26. //挖坑法
  27. private static int paririon(int[]array,int left,int right){
  28. int temp = array[left];
  29. while (left < right){
  30. while (left < right && array[right]<=temp){
  31. right--;
  32. }
  33. array[left] = array[right];
  34. while (left < right && array[left] > temp){
  35. left++;
  36. }
  37. array[right] =array[left];
  38. }
  39. array[left] = temp;
  40. return left;
  41. }
  42. //找到中间值的下标
  43. private static int midTreeNum(int[]array,int left,int right){
  44. //中间位置下标
  45. int mid = left+(right-left)/2;
  46. if(array[left]<array[right]){
  47. if(array[mid]<array[left]){
  48. return left;
  49. }else if(array[mid]>array[right]){
  50. return right;
  51. }else {
  52. return mid;
  53. }
  54. }else {
  55. if(array[mid]>array[left]){
  56. return left;
  57. }else if(array[mid]<array[right]){
  58. return right;
  59. }else {
  60. return mid;
  61. }
  62. }
  63. }
  64. private static void insertSort(int[]array,int left,int right){
  65. for(int i=left+1;i<=right;i++){
  66. int temp = array[i];
  67. int j = i-1;
  68. for(;j>=0;j--){
  69. if(array[j] > temp){
  70. array[j+1] = array[j];
  71. }else {
  72. break;
  73. }
  74. }
  75. array[j+1] = temp;
  76. }
  77. }

paririon 方法使用用来找到基准直的,通过找到的基准直将序列化分为两个子区间,再通过递归不断排序,缩小子区间,直到子区间就一个数字。

int index = midTreeNum(array,start,end);

这条语句什么意思? 就是取到三个数的中位数

三数取中原因:
如果这个序列是接近有序的,1 2 3 4 5 6 7 8 9 11 10
基准值一般选取最左侧的数据 1,那么每次递归1的左侧没有子序列,只有右侧
所以会大大提高时间复杂度,
那么就取最左,最有,最中三个数据的中位数,
将中位数与第一个数交换,这样返回的基准直就不是1了,而是与1交换的数

上面查找基准值的paririon方法是挖坑法

下面例举Hoare法查找基准值

  1. //Hoare法
  2. private static int paririon2(int[]array,int left,int right){
  3. int i = left;
  4. int temp = array[left];
  5. while (left < right){
  6. while (left < right && array[right] >= temp){
  7. right--;
  8. }
  9. while (left < right && array[left]<=temp){
  10. left++;
  11. }
  12. swap(array,left,right);
  13. }
  14. swap(array,left,i);
  15. return left;
  16. }

快速排序总结:

1.整体综合性能与使用场景都是比较好的,才敢较快排

2.时间复杂度:O(N*logN);

3.空间复杂度:O(logN);

4.稳定性:不稳定


2.归并排序

建立在归并操作上的有效排序算法,该算法采用分治法的一个典型的应用。将已有的子序列合并,得到完全有序的序列。

使每个子序列有序,再使每个子序列之间有序。

归并排序:

更多是解决磁盘中的外排序问题。

时间复杂度:O(N*logN)

空间复杂度:O(N)

稳定性:稳定

代码实现

  1. //归并排序
  2. public static void mergeSort(int[]array){
  3. megeFun(array,0,array.length-1);
  4. }
  5. public static void megeFun(int[]array,int left,int right){
  6. if(left >=right){
  7. return;
  8. }
  9. //分解
  10. int mid = left+(right-left)/2;
  11. megeFun(array,left,mid);
  12. megeFun(array,mid+1,right);
  13. //合并
  14. merge(array,left,mid,right);
  15. }
  16. public static void merge(int[]array,int left,int mid,int right){
  17. int[] temp = new int[right-left+1];
  18. int sl = left;
  19. int el = mid;
  20. int sr = mid+1;
  21. int er = right;
  22. int k = 0;
  23. while (sl<=el && sr<=er){
  24. if(array[sl] <= array[sr]){
  25. temp[k++] = array[sl++];
  26. }else{
  27. temp[k++] = array[sr++];
  28. }
  29. }
  30. while (sl<=el){
  31. temp[k++] = array[sl++];
  32. }
  33. while (sr<=er){
  34. temp[k++] = array[sr++];
  35. }
  36. for (int i = 0; i < k; i++) {
  37. array[i+left] = temp[i];
  38. }
  39. }


3.计数排序

又叫做鸽巢原理,是对哈希直接定址法的变形应用

1.统计相同元素的出现的次数

2.根据统计结果将序列收回到原来的序列中

时间复杂度:O(max(N,范围))

空间复杂度:O(范围)

稳定性:稳定

代码:

  1. public static void countSort(int[]array){
  2. //遍历数组找到最大最小值
  3. int mindex= array[0];
  4. int maxdex = array[0];
  5. for (int i = 0; i < array.length; i++) {
  6. if(maxdex<array[i]){
  7. maxdex = array[i];
  8. }
  9. if(mindex>array[i]){
  10. mindex = array[i];
  11. }
  12. }
  13. //已经找到最大与最小值了,定义数组
  14. int[]count = new int[maxdex-mindex+1];
  15. for (int i = 0; i < array.length; i++) {
  16. int val = array[i]-mindex;
  17. count[val]++;
  18. }
  19. //count数组以数据为下标,出现的次数为值
  20. int index = 0;//array的下标
  21. for (int i = 0; i < count.length ; i++) {
  22. while (count[i]>0){
  23. array[index] = i+mindex;
  24. index++;
  25. count[i]--;
  26. }
  27. }
  28. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/596562
推荐阅读
相关标签
  

闽ICP备14008679号