计数排序并非一种基于比较进行的排序,它是计算一个序列中的值在正常排好序中的序列所处的位置,怎么求解一个数的位置呢?就是利用下脚标进行求解,新建一个数组resu[],数组的长度要比序列中的最大值大1,数组中的值全部初始化为0,然后遍历原序列,将原序列的值i作为新建数组resu[]的下脚表,对resu[i]++操作,这样就得出值 i 出现的次数;然后再利用resu[i]=resu[i]+resu[i-1]求解出i在原序列中的位置。

计数排序需要两个额外的数组作辅助,提供临时存储的resu数组,存放最终排序结果的sorted_array数组,算法描述如下:

counting_sort(array,sorted_array)//

1、for i = 0 to max           //max为array中的最大值

2、  resu[i]=0;

3、for j= 1 to length(array)

4、  resu[array[j]]=resu[array[j]]+1       //求出包含array[i]的个数

5、for i=min+1 to max       //min为array中的最小值

6、  resu[i]=resu[i]+resu[i-1]     // i 在序列中的位置

7、for j=length(array) downto 1

8、  sorted_array[resu[array[j]]] = array[j]

 //如果arr[i]==arr[i-1]的话,显然要将arr[i-1]放到arr[i]之前

//所以要进行resu[arr[i]]--操作

9、  resu[array[j]] = resu[array[j]]-1 

以序列 2 5 3 1 2 3 1 3 为例,下图是实现该算法的排序过程

 

根据算法描述,可以写出如下程序: 

public class my{
    public static void main(String[] args)throws InterruptedException{
        int arr[]={2,5,3,2,2,3,2,1,3,9};
        int[] sorted_array=new int[arr.length];
        int max=arr[0],i=0,min=arr[0];
        //求出最小值和最大值
        for(int val:arr){
            max=max<val?val:max;
            min=min>val?val:min;
        }
        System.out.println("min = "+min);
        int[] resu=new int[max+1];
        for(int val:arr){
            resu[val]++;
        }
        for(i=min+1;i<=max;i++){
            resu[i]=resu[i]+resu[i-1];
        }
        for(i=arr.length-1;i>=0;i--){            
            sorted_array[resu[arr[i]]-1]=arr[i];
            //如果arr[i]==arr[i-1]的话,显然要将arr[i-1]放到arr[i]之前
            //所以要进行resu[arr[i]]--操作
            resu[arr[i]]--;
        }
        System.out.println();
        printArray(arr);
        printArray(sorted_array);
    }    
    static void printArray(int[] array){
        for(int val:array){
            System.out.print(val+" ");
        }
        System.out.println();
    }
}

 

可以看出,计数排序的时间复杂度是O(n),但空间复杂度是O(n),而且如果序列中的最大值如果远远大于序列长度的话,这种排序是很不划算的,因为空间浪费太大,但是对于给定范围0到k之间的数进行排序的话,效率还是挺高的,尤其是n非常大的情况下。

 

posted on 2017-08-23 22:04  Judy518  阅读(123)  评论(0编辑  收藏  举报