当前位置:   article > 正文

【八大排序④】归并排序、不基于比较的排序(计数排序、基数排序、桶排序)_归并排序 桶排序

归并排序 桶排序

目录

一、归并排序 

二、计数排序

三、基数排序 

四、桶排序


一、归并排序 

  归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤

  • 分解
  • 合并

 

 代码(递归)

  1. //归并排序
  2. public static void merge(int[] array,int low, int mid ,int high){
  3. int s1 = low;
  4. int e1 = mid;
  5. int s2 = mid+1;
  6. int e2 = high;
  7. int[] tmpArr = new int[high-low+1];
  8. int k = 0;
  9. //证明两个段都有数据
  10. while(s1 <= e1 && s2 <= e2){
  11. if(array[s1] < array[s2]){
  12. tmpArr[k++] = array[s1++];
  13. }else {
  14. tmpArr[k++] = array[s2++];
  15. }
  16. }
  17. while (s1 <= e1){
  18. tmpArr[k++] = array[s1++];
  19. }
  20. while (s2 <= e2){
  21. tmpArr[k++] = array[s2++];
  22. }
  23. for(int i = 0; i < k; i++){
  24. array[i+low] = tmpArr[i];
  25. }
  26. }
  27. public static void mergeSortInternal(int[] array,int low, int high){
  28. if(low >= high) return; //递归结束条件
  29. int mid = low + ((high-low) >>> 1) ;
  30. mergeSortInternal(array,low,mid);
  31. mergeSortInternal(array,mid+1,high);
  32. merge(array,low,mid,high);
  33. }
  34. public static void mergeSort(int[] array){
  35. mergeSortInternal(array,0,array.length-1);
  36. }

 

代码(非递归)

  1. public static void merge(int[] array,int low, int mid ,int high){
  2. int s1 = low;
  3. int e1 = mid;
  4. int s2 = mid+1;
  5. int e2 = high;
  6. int[] tmpArr = new int[high-low+1];
  7. int k = 0;
  8. //证明两个段都有数据
  9. while(s1 <= e1 && s2 <= e2){
  10. if(array[s1] < array[s2]){
  11. tmpArr[k++] = array[s1++];
  12. }else {
  13. tmpArr[k++] = array[s2++];
  14. }
  15. }
  16. while (s1 <= e1){
  17. tmpArr[k++] = array[s1++];
  18. }
  19. while (s2 <= e2){
  20. tmpArr[k++] = array[s2++];
  21. }
  22. for(int i = 0; i < k; i++){
  23. array[i+low] = tmpArr[i];
  24. }
  25. }
  26. //归并排序(非递归)
  27. public static void mergeSortNor(int[] array){
  28. int gap = 1;
  29. while(gap < array.length){
  30. for(int i = 0; i < array.length; i += 2*gap){
  31. int left = i;
  32. int mid = left+gap-1;
  33. //修正mid,防止越界
  34. if(mid >= array.length){
  35. mid = array.length-1;
  36. }
  37. int right = mid+gap;
  38. //修正right
  39. if(right >= array.length){
  40. right = array.length-1;
  41. }
  42. merge(array,left,mid,right);
  43. }
  44. }
  45. }

 

归并排序总结

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

   

二、计数排序

思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤:
1. 统计相同元素出现次数
2. 根据统计的结果将序列回收到原来的序列中

算法的步骤如下:

  • (1)找出待排序的数组中最大和最小的元素
  • (2)统计数组中每个值为i的元素出现的次数,存入数组C的第i项
  • (3)对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
  • (4)反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

 代码

  1. public static void countSort(int[] array){
  2. //1.获取最大值和最小值
  3. int maxVal = array[0];
  4. int minVal = array[0];
  5. for(int i = 1; i < array.length;i++){
  6. if(maxVal < array[i]){
  7. maxVal = array[i];
  8. }
  9. if(minVal > array[i]){
  10. minVal = array[i];
  11. }
  12. }
  13. //2.开始计数
  14. int range = maxVal-minVal+1;
  15. int[] count = new int[range];
  16. for (int i = 0; i < array.length; i++) {
  17. count[array[i] - minVal]++;
  18. }
  19. //3.遍历这个计数的数组,把数据放回array
  20. int index = 0;
  21. for (int i = 0; i < count.length; i++) {
  22. while(count[i]>0) {
  23. array[index++] = i + minVal;
  24. count[i]--;
  25. }
  26. }
  27. }

 【计数排序的特性总结】
1. 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。
2. 时间复杂度:O(MAX(N,范围))
3. 空间复杂度:O(范围)
4. 稳定性:稳定

   

三、基数排序 

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。 

算法描述

  • 取得数组中的最大数,并取得位数
  • 先按个位,个位为0的放在0下标处,个位为1放在1下标处,个位为n放在n下标处
  • 再遍历下标,把每个数一一取出
  • 再按十位,十位为0的放在0下标处,十位为1放在1下标处,十位为n放在n下标处
  • 再遍历下标,把每个数一一取出
  • 重复以上步骤,直到按最高位的也操作完就排完序了

 

四、桶排序

 思想:

划分多个范围相同的区间,每个子区间自排序,最后合并

图源网络 

 

 

 

 

 

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

闽ICP备14008679号