码迷,mamicode.com
首页 > 其他好文 > 详细

排序算法(二)

时间:2014-09-29 19:42:52      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   os   ar   java   strong   for   文件   

一、桶排序

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

排序算法(二)

标签:style   blog   color   os   ar   java   strong   for   文件   

原文地址:http://www.cnblogs.com/bukekangli/p/3991736.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!