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


    目录

    一、归并排序 

    二、计数排序

    三、基数排序 

    四、桶排序


    一、归并排序 

      归并排序(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下标处
    • 再遍历下标,把每个数一一取出
    • 重复以上步骤,直到按最高位的也操作完就排完序了

     

    四、桶排序

     思想:

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

    图源网络 

     

     

     

     

     

  • 相关阅读:
    多功能电力仪表在物联网的应用
    在 WPF 客户端实现 AOP 和接口缓存
    【kubernetes】带你入门k8s中的HPA
    vue学习之v-if/v-else/v-else-if
    vue项目中订单完成提交按钮动画
    从零开始操作系统-09:键盘实现
    数据库——《数据定义》
    Python基础入门篇【3】--变量与关键字
    【Python】用Python生成图像特效
    【pwn】2022 羊城杯 fakeNoOutput
  • 原文地址:https://blog.csdn.net/Living_Amethyst/article/details/125539027