排序算法——计数排序
一、比较计数排序
 
1、描述
2、算法(伪代码)
ComparisonCountingSort (A[0..n-1])//用比较计数法对数组排序//输入:可排序数组A[0..n-1]//输出:将A中元素按照升序排列的数组S[0..n-1]for i←0 to n-1 do Count[i]←0for i←0 to n-2 dofor j←i+1 to n-1 doif A[i]>A[j]Count[i]←Count[i]+1else Count[j]←Count[j]+1for i←0 to n-1 do S[Count[i]]←A[i]return S
3、源代码(Java语言)
/*** Project: Algorithm* Date: 2020/02/02* Time: 20:20* author: Eric* Description: TODO 计数排序*/public class CountingSort {/*** 用比较计数算法对数组排序** @param array 待排序数组* @return 升序排列的结果数组*/public static int[] comparisonCountingSort(int[] array) {int n = array.length;int[] count = new int[n]; //count初始化为0,记录小于该元素的元素个数int[] result = new int[n]; //存放排序结果的数组for (int i = 0; i < n - 1; ++i) {for (int j = i + 1; j < n; ++j) {if (array[i] < array[j]) {count[j] += 1;} else {count[i] += 1;}}}for (int i = 0; i < n; ++i) {result[count[i]] = array[i];}return result;}/*** 在控制台输出显示数组内容** @param array 待显示的数组*/private static void showArray(int[] array){for(int element:array){System.out.print(element+" ");}System.out.println();}//主方法(测试)public static void main(String[] args) {int[] array = {34, 62, 28, 73, 51, 46};int[] rs = comparisonCountingSort(array);System.out.println("原数组array:");showArray(array);System.out.println("利用比较计数排序后数组array:");showArray(rs);}}
4、测试结果
5、算法分析
此算法时间复杂度属于O(n²),它的基本操作(A[i]>A[j])的执行次数等于下面这个求和式。
此算法使用了两个空间容量与待排序数组相同的数组(Count[]和S[]),空间复杂度为O(n)。
二、分布计数排序
1、描述
| 数组值 | 11 | 12 | 13 | 
| 频率 | 1 | 3 | 2 | 
| 分布值 | 1 | 4 | 6 | 
注意:分布值指出了在最后的有序数组中,它们的元素最后一次出现时的正确位置。如果我们从0到n-1建立数组的下标,为了得到相应的元素位置,分布值必须减1。
所以排序结果数组为S=[11, 12, 12, 12, 13, 13]。
2、算法(伪代码)
DistributionCountingSort(A[0..n-1], low, high)//用分布计数算法,对来自于有限范围整数的一个数组进行排序//输入:数组A[0..n-1],数组中的整数位于low和high之间(low≤high)//输出:A中元素构成的非降序数组S[0..n-1]for i←0 to high-low do D[i]←0 // 初始化频率数组for i←0 to n-1 do D[A[i]-low]←D[A[i]-low]+1 // 计算频率值for i←1 to high-low do D[i]←D[i-1]+D[i] // 计算分布值for i←n-1 downto 0 do // 从右往左扫描数组j=A[i]-lowS[D[j]-1]←A[i] // 排序数组的下标比分布值要小1D[j]←D[j]-1 // 相应的分布值减1return S
3、源代码(Java语言)
/*** Project: Algorithm* Date: 2019/11/11* Time: 20:32* author: Eric* Description: TODO 计数排序*/public class CountingSort {/*** 用分布计数法,对来自有限范围整数的一个数组进行排序** @param array 可排序数组,数组整数值为有限范围* @param lo 整数的下界* @param hi 整数的上界* @return 非降序数组*/public static int[] distributionCountingSort(int[] array, int lo, int hi) {int n = array.length;int[] result = new int[n];int[] distribution = new int[hi - lo + 1]; //初始化分布值数组为0//计算频率值for (int i = 0; i < n; ++i) {distribution[array[i] - lo] += 1;}//计算分布值for (int i = 1; i < distribution.length; ++i) {distribution[i] += distribution[i - 1];}//从后往前扫描array数组利用分布值排序for (int i = n - 1; i >= 0; --i) {int index = array[i] - lo; //分布值数组中的下标//把array中元素放到结果数组中的合适位置result[distribution[index] - 1] = array[i];distribution[index] -= 1;//相应的分布值减1}return result;}/*** 在控制台输出显示数组内容** @param array 待显示的数组*/private static void showArray(int[] array){for(int element:array){System.out.print(element+" ");}System.out.println();}//主方法(测试)public static void main(String[] args) {int[] array = {13, 11, 12, 13, 12, 12};int[] rs = distributionCountingSort(array, 11, 13);System.out.println("原数组array:");showArray(array);System.out.println("利用比较计数排序后数组array:");showArray(rs);}}
4、测试结果
5、算法分析
参考资料:
[美]Anany Levitin著. 算法分析与设计基础第3版. 潘彦译. 北京: 清华大学出版社, 2015
