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

目录

一、归并排序 

二、计数排序

三、基数排序 

四、桶排序


一、归并排序 

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

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

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

  • 分解
  • 合并

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

 代码(递归)

//归并排序
    public static void merge(int[] array,int low, int mid ,int high){
        int s1 = low;
        int e1 = mid;
        int s2 = mid+1;
        int e2 = high;
        int[] tmpArr = new int[high-low+1];
        int k = 0;
        //证明两个段都有数据
        while(s1 <= e1 && s2 <= e2){
            if(array[s1] < array[s2]){
                tmpArr[k++] = array[s1++];
            }else {
                tmpArr[k++] = array[s2++];
            }
        }
        while (s1 <= e1){
            tmpArr[k++] = array[s1++];
        }
        while (s2 <= e2){
            tmpArr[k++] = array[s2++];
        }

        for(int i = 0; i < k; i++){
            array[i+low] = tmpArr[i];
        }

    }
    public static void  mergeSortInternal(int[] array,int low, int high){
        if(low >= high) return;  //递归结束条件
        int mid = low + ((high-low) >>> 1) ;

        mergeSortInternal(array,low,mid);
        mergeSortInternal(array,mid+1,high);

        merge(array,low,mid,high);
    }
    public static void mergeSort(int[] array){
        mergeSortInternal(array,0,array.length-1);
    }

 

代码(非递归)

 public static void merge(int[] array,int low, int mid ,int high){
        int s1 = low;
        int e1 = mid;
        int s2 = mid+1;
        int e2 = high;
        int[] tmpArr = new int[high-low+1];
        int k = 0;
        //证明两个段都有数据
        while(s1 <= e1 && s2 <= e2){
            if(array[s1] < array[s2]){
                tmpArr[k++] = array[s1++];
            }else {
                tmpArr[k++] = array[s2++];
            }
        }
        while (s1 <= e1){
            tmpArr[k++] = array[s1++];
        }
        while (s2 <= e2){
            tmpArr[k++] = array[s2++];
        }

        for(int i = 0; i < k; i++){
            array[i+low] = tmpArr[i];
        }

    }
//归并排序(非递归)
    public static void mergeSortNor(int[] array){
        int gap = 1;
        while(gap < array.length){
            for(int i = 0; i < array.length; i += 2*gap){
                int left = i;
                int mid = left+gap-1;
                //修正mid,防止越界
                if(mid >= array.length){
                    mid = array.length-1;
                }
                int right = mid+gap;
                //修正right
                if(right >= array.length){
                    right = array.length-1;
                }
                merge(array,left,mid,right);
            }
        }
    }

 

归并排序总结

  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

 代码

   public static void countSort(int[] array){
        //1.获取最大值和最小值
        int maxVal = array[0];
        int minVal = array[0];
        for(int i = 1; i < array.length;i++){
            if(maxVal < array[i]){
                maxVal = array[i];
            }
            if(minVal > array[i]){
                minVal = array[i];
            }
        }
        //2.开始计数
        int range = maxVal-minVal+1;
        int[] count = new int[range];
        for (int i = 0; i < array.length; i++) {
            count[array[i] - minVal]++;
        }
        //3.遍历这个计数的数组,把数据放回array
        int index = 0;
        for (int i = 0; i < count.length; i++) {
            while(count[i]>0) {
                array[index++] = i + minVal;
                count[i]--;
            }
        }
    }

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

   

三、基数排序 

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

算法描述

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

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

 

四、桶排序

 思想:

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

图源网络 

 

 

 

 

 

你可能感兴趣的:(数据结构,算法,排序算法,java)