我是一个从汽车行业转行IT的项目经理,我是Edward,如想了解更多,请关注我的公众号【转行项目经理的逆袭之路】。今天来聊聊桶原理的第一种排序方法,一种非基于比较的排序方法,计数排序
计数排序
计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)。
适用场景
适用于数据多范围小的情况,比如:年龄、分数段等。
推演步骤
- 1:自建特殊数组(比如:数量自定,范围0-9)写个小程序测试一下
- 2:放进新数组计算出现频率,再取出,不稳定。 优化。
- 3:设置count累加数组,倒序遍历,挨个放回,保证稳定。
Java实现
package algorithm;
import java.util.Arrays;
/**
* 计数算法
* 适用于数据多范围小的情况
* 1:自建特殊数组(比如:数量自定,范围0-9)写个小程序测试一下
* 2:放进新数组计算出现频率,再取出,不稳定。 优化。
* 3:设置count累加数组,倒序遍历,挨个放回,保证稳定。
* @author EP
* @date 2020年4月15日
* @version 1.0
*/
public class CountSort {
public static void main(String[] args) {
//0,0,1,2,2,2,2,3,3...
int[]arr = {2,4,3,6,4,0,2,5,6,1,2,0,8,6,7,5,9,8,4,9,4,3,2,7,5,6};
int[]result=sort(arr);
System.out.println(Arrays.toString(result));
}
static int[] sort(int[]arr){
int[]result = new int[arr.length];
int[]count = new int[10];
for (int i = 0; i < arr.length; i++) { //记录每个数字出现的次数
count[arr[i]]++;
}
System.out.println(Arrays.toString(count));
int index=0;
// for (int i = 0,j = 0; i < count.length; i++) {
// while (count[i]-- >0) { //优化一下代码
// result[j++]=i;
count[i]--;
// }
// }
for (int i = 1; i < count.length; i++) {
count[i]=count[i]+count[i-1];
}
System.out.println(Arrays.toString(count));
for (int i = result.length-1; i >=0; i--) {
result[--count[arr[i]]]=arr[i]; //先--,否则下标越界
}
return result;
}
}
留给大家一个思考的问题:
如果数据不是均匀分布在给定区间内,如何预先通过判断数据的分布情况简化排序的复杂度呢?(比如,数据为1-100区间,但是70-100区间内数据仅有几个,是否也需要把这个区间内单另设k长度数组呢。)