原理:用一个数组记录待排序数组中出现的数字。
最低位代表最小值,偏移量是记录数组中的下标;
待排序数组: 2 1 4 可以表示为
记录数组: 1 1 0 1 数组长度为(4-1+1)
然后根据记录数组输出结果
public static void countSort(int [] arr){
if(arr==null){
return;
}
if(arr.length<=1){
return;
}
int maxValue=getMax(arr);
int minValue=getMin(arr);
// 创建一个数组来记录出现的数字
int[] recordArr=new int[maxValue-minValue+1];
// 看一下哪个数字出现了
for(int i=0;i<arr.length;i++){
int curNum=arr[i];
// 记录出现的数字以及他出现的次数
recordArr[curNum-minValue]+=1;
}
// 输出出现在待排序数组中出现的数字
int curArrIndex=0;
int len=arr.length;
int curRecordIndex=0;
while (curArrIndex<len){
if(recordArr[curRecordIndex]>0){
// 该数字在待排序数组中出现
arr[curArrIndex]=minValue+curArrIndex;
recordArr[curArrIndex]--;
curArrIndex++;
}else {
// 该书在在待排序数组中没有出现
curRecordIndex++;
}
}
}
// 获取数组中的最大值
public static int getMax(int [] arr){
int res=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++){
if(res<arr[i]){
res=arr[i];
}
}
return res;
}
// 获取数组中的最小只
public static int getMin(int []arr){
int res=Integer.MAX_VALUE;
for(int i=0;i<arr.length;i++){
if(res>arr[i]){
res=arr[i];
}
}
return res;
}
但上面这种方法,本质上并未对待排序数组进行排序(操作),如果排序的是对象的话,就无法使用,而且也不能解决稳定性问题
解决方法:
在获得记录数组后,更新记录数组,每一位+=前一位,这样一来,记录数组的值-1代表 所记录数字在排序结果中的下标
待排序数组:1 4 2
记录数组:1 1 0 1
更新后: 1 2 2 3
从后面读起:
待排序数组中,2对应位置为下标2-1;4对应下标为3-1;1对应下表为1-1
//进化版计数排序
// 由于初级版本通过记录出现的数字,然后直接输出获得数组,并没有实际操作待排序数组
// 这种排序只能对对象进行排序,并且是不稳定的
public static void countSort(int[] arr){
if(arr==null||arr.length<=1){
return;
}
int maxValue=getMax(arr);
int minValue=getMin(arr);
// 创建一个数组来记录出现的数字
int[] recordArr=new int[maxValue-minValue+1];
// 看一下哪个数字出现了
for(int i=0;i<arr.length;i++){
int curNum=arr[i];
// 记录出现的数字以及他出现的次数
recordArr[curNum-minValue]+=1;
}
// 更新记录数组
for(int i=1;i<recordArr.length;i++){
recordArr[i]+=recordArr[i-1];
}
int []res=new int[arr.length];
for(int i=arr.length-1;i>=0;i--){
int curValue=arr[i];
// 获得当前数字的 排序后下标
int index=recordArr[curValue-minValue]-1;
recordArr[curValue-minValue]--;
res[index]=curValue;
}
arr=res;
}
// 获取数组中的最大值
public static int getMax(int [] arr){
int res=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++){
if(res<arr[i]){
res=arr[i];
}
}
return res;
}
// 获取数组中的最小只
public static int getMin(int []arr){
int res=Integer.MAX_VALUE;
for(int i=0;i<arr.length;i++){
if(res>arr[i]){
res=arr[i];
}
}
return res;
}