• 排序算法(二)


    一、桶排序

    (1)算法描述:假设数组元素值的范围是0~n-1。我们需要N个标记为0,1,2,...,n的桶。如果元素的值是i,那么就将该元素放入桶i中。然后将0~n-1号桶中的元素放回原数组,即可得到从小到大的序列。

    public static <E>void bucketSort(E[] list){//list为数组
        E[] buckets=(E[])new java.util.ArrayList[N];
            //将元素放入桶
        for(int i=0;i<list.length;i++){
            int key=list[i];
            if(buckets[key]=null){
                buckets[key]=new java.util.ArrayList();
            }
    
            buckets[key].add(list[i]);
        }
            //将桶中的元素放回数组
        int k=0;
        for(int i=0;i<buckets.length;i++){
            if(buckets[i]!=null){
                for(int j=0;j<buckets[i].size();j++){
                    list[k++]=buckets[i].get(j);
                }
            }
        }
    }

    (2)算法实现

    package algorithm;
    
    import java.util.ArrayList;
    
    public class BucketsSort{
        public static <E> void bucketSort(E[] list,int max){//list为数组
        E[] buckets=(E[]) new java.util.ArrayList[max+1];//声明
    
        for(int i=0;i<list.length;i++){
            int key=(Integer) list[i];
            if(buckets[key]==null){
                buckets[key]=(E) new java.util.ArrayList();//初始化
            }
    
            ((ArrayList) buckets[key]).add(list[i]);
        }
    
        int k=0;
        for(int i=0;i<buckets.length;i++){
            if(buckets[i]!=null){
                for(int j=0;j<((ArrayList) buckets[i]).size();j++){
                    list[k++]=(E) ((ArrayList) buckets[i]).get(j);
                }
            }
        }
    }
    
        public static void main(String[] args){
            Integer[] list={8,3,2,4,7,9};
            int max=9;
            BucketsSort.<Integer>bucketSort(list,max);
    
            for(Integer u:list)
                System.out.print(u+",");
        }
    }

    (3)总结:桶排序的时间为O(n+N),n表示线性表的大小。桶排序不是基于比较排序的,因此好过比较排序算法的下限O(nlogn)。桶排序是稳定的。

    二、基数排序

    1.最低位优先(Least Significant Digit first)法,简称LSD法

    (1)算法描述:

       第一步:建立10个桶,对应着编号0-9.位置关键字k=1,表示从最低位开始。

       第二步:遍历需要排序的序列。数把序列中的数分配到第k位数对应的桶里。

       第三步:遍历桶,从0-9把桶中的数据依次放回到原数组中!

       第四步:如果k的等于序列中最大数的最高位数,则排序结束。否则k=k+1,跳转到第二步。

    2.最高位优先(Most Significant Digit first)法,简称MSD法

    (1)算法描述:

       从最高位开始,实际上已经能保证大体上是从小到大的递增序列了!但是位数相同时,就不一定了!实际上就是:桶外有序,而桶类无序!这时候,就是递归的思想起作用了!既然桶外有序,我们就不管桶外了,关注处理桶内的数据。从次高位开始,再建立10个桶,然后把数据放到桶里,按第一次的方式来处理,直到处理到最低位!

    3.算法实现

    import java.util.ArrayList;
    
    public class RadixSort {
        public static void main(String[] args){
            Integer[] a={122,55,422,333,655,599,799};
            Integer[] b={122,55,422,333,655,599,799};
            RadixSort.LSD(a,3);
            System.out.println();
            RadixSort.MSD(b,3);
            
            for(Integer  u:b)
                System.out.print(u+",");
        }
        //最低位优先(Least Significant Digit first)法
        @SuppressWarnings("unchecked")
        public static void LSD(Integer[] a,int d){
            ArrayList[] buckets=new java.util.ArrayList[10];
            //数据有d位数
            for(int x=0;x<d;x++){
                //将数据放入桶
                for(int i=0;i<a.length;i++){                
                    int[] r=getr( a[i],d);                 
                    if(buckets[r[x]]==null)
                        buckets[r[x]]=new java.util.ArrayList<Integer>();
                    
                    buckets[r[x]].add(a[i]);                
                }            
                //将桶中数据放数组
                int k=0;
                for(int j=0;j<10;j++){
                    if(buckets[j]!=null){
                        for(int y=0;y<buckets[j].size();y++){
                            a[k++]=(Integer) buckets[j].get(y);
                    
                        }
                        buckets[j].clear();//清空桶,否则元素会重复聚集,导致数组a下标异常
                    }                
                }        
            }        
            //打印数据
            for(Integer  u:a)
                System.out.print(u+",");        
        }
        
        //最高位优先(Most Significant Digit first)法
        public static void MSD(Integer[] a,int d){
            MSD(a,0,a.length,d);
        }
        
        public static void MSD(Integer[] a,int n1,int n2,int d){//对a[n1,n1+n2)部分元素排序,n1为子数组起始下标,n2为元素个数
            if(d>0){
                ArrayList[] buckets=new java.util.ArrayList[10];
                //将数组数据放入桶
                for(int i=n1;i<n1+n2;i++){                
                    int[] r=getr( a[i],d);                 
                    if(buckets[r[d-1]]==null)
                        buckets[r[d-1]]=new java.util.ArrayList<Integer>();
                    
                    buckets[r[d-1]].add(a[i]);                
                }
                //将桶中数据放回数组        
                for(int j=0;j<10;j++){
                    int num=0;//记录每个桶中元素个数
                    if(buckets[j]!=null){                    
                        for(int y=0;y<buckets[j].size();y++){
                            a[n1++]=(Integer)buckets[j].get(y);
                            num++;
                        }                    
                        buckets[j].clear();//清空桶,否则元素会重复聚集,导致数组a下标异常,对于MSD方法,此步骤可省略,因为每次递归都会新建buckets数组没有重用buckets数组
                    }                
                    MSD(a,n1-num,num,d-1);//对每个桶中的元素递归排序
                }                
            }        
        }
        //返回由数据各位组成的数组
        public static int[] getr(int n,int d){
            int[] r=new int[d];
            for(int i=0;i<d;i++){
                r[i]=n%10;
                n=n/10;
            }
            return r;
        }
    }

    三、外部排序

       要对存储在外部文件中的数据进行排序,首先要将数据送入内存,然后排序。但当文件过大时,所有数据不能同时送入内存。解决方法:

    (1)重复将文件读入数组,并调用内部排序算法对数组排序,然后将数组输出到一个临时文件;

    (2)将每对有序分段归并到一个大一些的有序分段中,将新分段存储到新的临时文件。继续同样的过程直到得到一个有序分段。(归并排序)

    排序复杂度:O(nlogn)

  • 相关阅读:
    UE4使用第三方库读写xml文件
    ROS机器人程序设计(原书第2版)补充资料 教学大纲
    Unity UGUI图文混排(七) -- 下划线
    奥比中光Orbbec Astra Pro RGBD 3D视觉传感器在ROS(indigo和kinetic)使用说明 rgb depth同时显示
    Java复习之泛型
    Java复习之多线程
    Java复习之包及访问控制权限
    Java复习之异常
    Java复习之面向对象高级
    Java复习之面向对象基础
  • 原文地址:https://www.cnblogs.com/bukekangli/p/3991736.html
Copyright © 2020-2023  润新知