十大排序算法之四 - 计数排序
1.计数排序的介绍
- 计数排序,这种排序算法是利用数组下标来确定元素的正确位置的
- 假设数组中有10个整数,取值范围为0~10,要求用最快的速度把这10个整数从小到大进行排序,可以根据这有限的范围,建立一个长度为11的数组。数组下标从0到10,元素初始值全为0
- 假设数组数据为:9,1,2,7,8,1,3,6,5,3
- 下面就开始遍历这个无序的随机数列,每一个整数按照其值对号入座,同时,对应数组下标的元素进行加1操作
- 该数组中每一个下标位置的值代表数列中对应整数出现的次数
- 计数排序:适合于连续的取值范围不大的数组,不连续和取值范围过大会造成数组过大
- 如果起始数不是从0开始,比如分数排序:95,94,91,98,99,90,99,93,91,92,数组起始数为90,这样数组前面的位置就浪费了,可以采用偏移量的方式:
2.Java实现计数排序
(此处内部实现查找最小值(小顶堆实现),进行偏移,然后再进行计数排序,从而为用户节省了一部分操作)
package com.lagou.calculateSort;
import java.util.Arrays;
/**
* @author 云梦归遥
* @date 2022/5/18 10:55
* @description 计数排序
*/
public class CalculateSortMethod {
// 计数排序
public int[] calculateSort(int[] array){
int length = array.length; // 记录数组长度
// 将原数组复制一份构建小顶堆
int[] arrayCopy = new int[length];
System.arraycopy(array, 0, arrayCopy, 0, length);
int min = min(arrayCopy); // 获取小顶堆堆顶(数组最小元素)
// 构建计数数组,用于记录各个数的数量
int[] arrayCount = new int[length];
for (int i = 0; i < length; i++){
arrayCount[array[i] - min]++;
}
// 用于构建结果数组
int[] arrayResult = new int[length];
for (int i = 0, index = 0; i < length; i++){
for (int j = 0; j < arrayCount[i]; j++){
arrayResult[index++] = min + i;
}
}
return arrayResult;
}
// 获取数组中的最小值
private int min(int[] array){
for (int i = array.length / 2 - 1; i >= 0; i--){
createHeapMinSort(array, i, array.length);
}
// 返回第一个数据就是最小的树
return array[0];
}
// 通过小顶堆实现寻找数组中的最小值,实现偏移存储
private void createHeapMinSort(int[] array, int parent, int length){
for (int i = parent * 2 + 1; i < length; i = i * 2 + 1){
// 左节点大于右节点,以右节点来判断
if (i + 1 < length && array[i] > array[i + 1]){
i++;
}
if (array[parent] > array[i]){
int temp = array[i];
array[i] = array[parent];
array[parent] = temp;
// 将子节点作为父节点继续向下构建小顶堆
parent = i;
} else {
// 下面已经是小顶堆了
break;
}
}
}
}
进行测试
package com.lagou.calculateSort.test;
import com.lagou.calculateSort.CalculateSortMethod;
import java.util.Arrays;
/**
* @author 云梦归遥
* @date 2022/5/18 11:26
* @description
*/
public class CalculateSortMethodTest {
public static void main(String[] args) {
CalculateSortMethod calculateSortMethod = new CalculateSortMethod();
int[] array = {3, 2, 5, 7, 4, 1, 9, 6, 8};
System.out.println("【计数排序 - 前】" + Arrays.toString(array));
int[] sort = calculateSortMethod.calculateSort(array);
System.out.println("【计数排序 - 后】" + Arrays.toString(sort));
}
}
3.总结
- 计数排序的时间复杂度是O(n)