前面介绍的几种排序算法,都是基于不同位置的元素比较,算法平均时间复杂度理论最好值是θ(nlgn).

今天介绍一种新的排序算法,计数排序(Counting sort),计数排序是一个非基于比较的线性时间排序算法。它对输入的数据有附加的限制条件:输入序列中数据取值范围有限,比如都是小于upperLimit的整数;

算法分3步实现:

1)遍历输入序列,统计不同取值的个数,放入计数数组;

2)遍历计数数组,计算不大于各个取值的个数,更新计数数组;

3)逆序遍历输入序列,结合计数数组中个数,将数据放到输出数组中。

(一)算法实现

 

 1 protected void sort(int[] toSort) {
 2         int[] result = new int[toSort.length];
 3         int[] countingArray = new int[upperLimit];
 4         for (int i = 0; i < toSort.length; i++) {
 5             countingArray[toSort[i]]++;
 6         }
 7         for (int i = 1; i < countingArray.length; i++) {
 8             countingArray[i] += countingArray[i - 1];
 9         }
10 
11         for (int i = toSort.length - 1; i >= 0; i--) {
12             result[countingArray[toSort[i]] - 1] = toSort[i];
13             countingArray[toSort[i]]--;
14         }
15 
16         System.arraycopy(result, 0, toSort, 0, result.length);
17     }
Counting Sort

1)算法时间复杂是θ(n+k),n表示输入序列中元素个数,k表示输入序列中元素取值集合的个数;

2)算法属于稳定排序;

3)算法不属于原地排序,需要额外空间存放计数数组和输出数组,空间复杂度是θ(n+k);

4)算法不是比较排序算法。

(二)仿真结果

 下面是计数排序和随机化排序的比较,从结果看,当k=O(n)时,计数排序时间复杂度更低。

**************************************************
Number to Sort is:2500
Array to sort is:{735805,621178,561545,362760,60951,337406,317120,378387,25311,115277...}
Cost time of 【CountingSort】 is(milliseconds):4
Sort result of 【CountingSort】:{177,418,611,924,1139,1752,2048,2221,2918,3340...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):0
Sort result of 【RandomizedQuickSort】:{177,418,611,924,1139,1752,2048,2221,2918,3340...}
**************************************************
Number to Sort is:25000
Array to sort is:{435929,221392,407142,872904,594585,726112,958590,976368,570033,848066...}
Cost time of 【CountingSort】 is(milliseconds):5
Sort result of 【CountingSort】:{24,42,79,134,142,257,268,462,503,544...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):2
Sort result of 【RandomizedQuickSort】:{24,42,79,134,142,257,268,462,503,544...}
**************************************************
Number to Sort is:250000
Array to sort is:{426400,121941,600931,85753,455109,650154,341754,478839,921893,648842...}
Cost time of 【CountingSort】 is(milliseconds):16
Sort result of 【CountingSort】:{0,2,6,23,33,34,35,38,41,46...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):28
Sort result of 【RandomizedQuickSort】:{0,2,6,23,33,34,35,38,41,46...}
**************************************************
Number to Sort is:2500000
Array to sort is:{26177,919623,668931,41665,236093,656020,473433,258087,659468,419426...}
Cost time of 【CountingSort】 is(milliseconds):206
Sort result of 【CountingSort】:{0,0,0,2,3,3,4,4,5,5...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):334
Sort result of 【RandomizedQuickSort】:{0,0,0,2,3,3,4,4,5,5...}

相关代码:

 1 package com.cnblogs.riyueshiwang.sort;
 2 
 3 import java.util.Arrays;
 4 
 5 public class CountingSort extends abstractSort {
 6 
 7     private int upperLimit;
 8 
 9     public CountingSort(int upperLimit) {
10         this.upperLimit = upperLimit;
11     }
12 
13     @Override
14     protected void sort(int[] toSort) {
15         int[] result = new int[toSort.length];
16         int[] countingArray = new int[upperLimit];
17         for (int i = 0; i < toSort.length; i++) {
18             countingArray[toSort[i]]++;
19         }
20         for (int i = 1; i < countingArray.length; i++) {
21             countingArray[i] += countingArray[i - 1];
22         }
23 
24         for (int i = toSort.length - 1; i >= 0; i--) {
25             result[countingArray[toSort[i]] - 1] = toSort[i];
26             countingArray[toSort[i]]--;
27         }
28 
29         System.arraycopy(result, 0, toSort, 0, result.length);
30     }
31 
32     public static void main(String[] args) {
33         for (int j = 0, n = 2500; j < 4; j++, n = n * 10) {
34             System.out
35                     .println("**************************************************");
36             System.out.println("Number to Sort is:" + n);
37             int upperLimit = 1000000;
38             int[] array = CommonUtils.getRandomIntArray(n, upperLimit);
39             System.out.print("Array to sort is:");
40             CommonUtils.printIntArray(array);
41 
42             int[] array1 = Arrays.copyOf(array, n);
43             new CountingSort(upperLimit).sortAndprint(array1);
44 
45             int[] array2 = Arrays.copyOf(array, n);
46             new RandomizedQuickSort().sortAndprint(array2);
47         }
48     }
49 }
CountingSort.java