首页 > 代码库 > 排序算法(二)

排序算法(二)

一、桶排序

(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)

排序算法(二)