持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
本文系作者 不太自律的程序猿原创,转载请私信并在文章开头附带作者和原文地址链接。
计数排序算法
计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)
算法思路
根据统计待排序数组中某个数大于等于其他数的个数来确定排序后所在的位置计数排序是一种非常快捷的稳定性强的排序方法,时间复杂度O(n+k),其中n为要排序的数的个数,k为要排序的数的组大值。计数排序对一定量的整数排序时候的速度非常快,一般快于其他排序算法。但计数排序局限性比较大,只限于对整数进行排序。消耗空间复杂度来获取快捷的排序方法,其空间复杂度为O(K),K为要排序的最大值。
1.首先找出待排序数组的最大值,用来创建临时空间,该临时空间的大小就是最大值+1;该临时空间用来存放每个数出现的次数。
- temp数组大小为9,下标范围为0-max,对于索引8来说,8在待排序数组中出现了1次,即temp[8]=1;对于索引6来说,6在在待排序数组中出现了2次,即temp[6]=2;以此类推。
- 对所有的计数进行累加,即对于第i个位置,统计小于等于i的所有个数,重新覆写到temp数组中,对于索引3来说,小于等于3的总个数为2。对于索引7来说,小于等于7的总个数为7。
4.反向填充目标数组:根据待排序数组中的元素值放在统计的个数值-1处,即对于待排序数8来说,首先找到temp的索引为8处,该统计的个数减去一,为7,即8放在排序结果数组的索引7处。即对于待排序数5来说,首先找到temp的索引为5处,该统计的个数减去一,为3,即5放在排序结果数组的索引3处。即对于待排序数6来说,首先找到temp的索引为6处,该统计的个数减去一,为5,即6放在排序结果数组的索引5处。对于第二个6来说,因为前面统计个数为5,这里减一为4,即第二个6放在排序结果数组的索引4处。
动态展示
代码实现
public static int[] countSort(int[] array) {
//1.得到数列的最大值,并计算出差值d
int max = array[0];
int min = array[0];
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
if (array[i] < min) {
min = array[i];
}
}
int d = max - min;
//2.创建统计数组并对统计对应元素的个数。
int[] countArray = new int[d + 1];
for (int i = 0; i < array.length; i++) {
countArray[array[i] - min]++;
}
//3.统计数组做变形,后面的元素等于前面的元素之和
for (int i = 1; i < countArray.length; i++) {
countArray[i] += countArray[i - 1];
}
//4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
int[] sortedArray = new int[array.length];
for (int i = array.length - 1; i >= 0; i--) {
sortedArray[countArray[array[i] - min] - 1] = array[i];
countArray[array[i] - min]--;
}
return sortedArray;
}
public static void main(String[] args) {
int[] arr = {8,1,2,7,6,5,4,3};
System.out.println("排序前:"+Arrays.toString(arr));
int[] sortedArray = countSort(arr);
System.out.println("排序后:"+Arrays.toString(sortedArray));
}
算法性能分析
时间复杂度
计数排序算法遍历了3次原始数组,一次计数数组,所以算法的时间复杂度是O(N+M)
空间复杂度
计数排序算法排序过程中新建了一个计数数组和一个输出数组,所以算法的空间复杂度是O(N+M)
感谢诸君的观看,文中如有纰漏,欢迎在评论区来交流。如果这篇文章帮助到了你,欢迎点赞👍关注。