排序算法补充总结(非比较排序)

Posted ohana!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法补充总结(非比较排序)相关的知识,希望对你有一定的参考价值。

目录

一,海量排序问题

1.基本情况

2.场景举例 

3.解决思路(解决办法)

二,计数排序(非比较排序)

1.基本思想(实现思路)

2.实现代码

3.性能分析

4.测试 

三,桶排序(简单了解)

1. 什么时候最快

2. 什么时候最慢

3. 示意图


一,海量排序问题

1.基本情况

当数据量非常庞大时,但是,内存只有1G,4G等等情况下,插入,交换,选择排序算法都只能把数据加载到内存去进行,此时,解决问题的方法就比较难了,但是也不是没有办法,我们可以使用归并排序,它的应用场景多是针对外部排序

  • 外部排序:排序过程需要在磁盘等外部存储进行的排序

2.场景举例 

此时有20个G的数据需要我们去进行排序,但是我们的计算机的内存只有4G,明显是内部排序不能满足的情况(就算全部让内存来运行排序也不行,实际情况是,计算机的操作系统,还有别的计算机的软件要同时运行,所以,内存是绝对不行的) 

3.解决思路(解决办法)

  • 先把文件切分成40份,每个512M
  • 分别对512 M排序,因为内存已经可以放的下,所以任意排序方式都可以
  • 进行40路归并,同时对40份有序文件做归并过程,最终结果就有序了

二,计数排序(非比较排序)

1.基本思想(实现思路)

  • 先对原数组出现元素的次数进行记录(创建一个新的数组)
  • 根据统计的结果,将数据还原到原来的数组当中

2.实现代码

    public static void countSort(int[] array)
        //先统计原来数组的元素进行处理----数据集中在某一个区间当中
        //就用最大值减去最小值在加一就是统计数组的长度
        int max = 0;
        int min = 0;
        for (int i = 0; i < array.length; i++) 
            //找最大元素的下标
            if(array[i] > array[max])
                max = i;
            
            //找最小元素的下标
            if(array[i] < array[min])
                min = i;
            
        

        //对原数组最大,最小的元素作差加一得到统计数组的长度
        int len = array[max] - array[min] + 1;
        int Min = array[min];
        //定义统计数组(用数组的值作为统计数组的下标)
        int[] arr = new int[len];
        for (int i = 0; i < array.length; i++) 
            arr[array[i] - Min]++;
        
        
        //这个j定义的实际上是原数组的下标,届时如果有相同的元素
        //那么统计数组的下标必然不会变,因此就需要我们定义一个下标来控制原数组的下标进行移动
        int j = 0;
        for (int i = 0; i < arr.length; i++) 
            //还原原数组
            int index = arr[i];
            //index控制同一个元素的连续传递给原数组
            while(index != 0)
                //需要注意的是,我们要对这个i再加上Min,因为,当时计算时是减去了最小值
                array[j] = i + Min;
                index--;
                j++;
            
        
    

3.性能分析

(1)时间复杂度:

  • 从一个层面来说,最坏的情况是外层循环走满,那么,这样内层循环就可以忽略,因此时间复杂度是O(N)

(2)空间复杂度:

  • 因为向外接住了一段辅助空间,但是,数组长度又不全是原数组的长度,不一定是O(N),视具体情况而定

(3)稳定性:

  • 稳定

(4)适用场景:

  • 适合于数据集中于某一个区间的时候

4.测试 

public class CountSort 
    public static void countSort(int[] array)
        //先统计原来数组的元素进行处理----数据集中在某一个区间当中
        //就用最大值减去最小值在加一就是统计数组的长度
        int max = 0;
        int min = 0;
        for (int i = 0; i < array.length; i++) 
            //找最大元素的下标
            if(array[i] > array[max])
                max = i;
            
            //找最小元素的下标
            if(array[i] < array[min])
                min = i;
            
        

        //对原数组最大,最小的元素作差加一得到统计数组的长度
        int len = array[max] - array[min] + 1;
        int Min = array[min];
        //定义统计数组(用数组的值作为统计数组的下标)
        int[] arr = new int[len];
        for (int i = 0; i < array.length; i++) 
            arr[array[i] - Min]++;
        

        //这个j定义的实际上是原数组的下标,届时如果有相同的元素
        //那么统计数组的下标必然不会变,因此就需要我们定义一个下标来控制原数组的下标进行移动
        int j = 0;
        for (int i = 0; i < arr.length; i++) 
            //还原原数组
            int index = arr[i];
            //index控制同一个元素的连续传递给原数组
            while(index != 0)
                //需要注意的是,我们要对这个i再加上Min,因为,当时计算时是减去了最小值
                array[j] = i + Min;
                index--;
                j++;
            
        
    
    public static void print(int[] array)
        for (int i = 0; i < array.length; i++) 
            System.out.print(array[i] + " ");
        
        System.out.println();
    
    public static void main(String[] args) 
        int[] array = 9,9,7,7,0,4,3,2,0,0;
        print(array);
        countSort(array);
        print(array);
    

三,桶排序(简单了解)

  • 桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:
  1. 在额外空间充足的情况下,尽量增大桶的数量
  2. 使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中
  • 同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要

1. 什么时候最快

当输入的数据可以均匀的分配到每一个桶中

2. 什么时候最慢

当输入的数据被分配到了同一个桶中

3. 示意图

元素分布在桶中:

然后,元素在每个桶中排序: 

以上是关于排序算法补充总结(非比较排序)的主要内容,如果未能解决你的问题,请参考以下文章

超详细总结基于比较的七大经典 排序 -- 不会的童鞋快进来补习

十大排序算法知识点总结

常用排序算法总结

js 常用的比较排序算法总结

十大经典排序算法的算法描述和代码实现

排序算法总结