像冒泡,选择,插入,堆,归并,希尔,快速 排序,这些是基于比较的 排序
而计数排序,桶排序,基数排序 这些都不是基于比较的排序,采用的思想是 以空间换时间
下面来介绍一下计数排序
-
计数的排序的核心思想
- 通过统计每个整数在序列中出现的次数,进而推导出每个整数在有序序列中的索引
因为要计算出排完顺序后 每个整数的最大位置,所以需要开辟一个数组进行存储
- 数组的长度 : 最大值 - 最小值
- 数组的定义 : 每个整数 - 最小值 就得到这个整数的索引
- 数组的值 : 排完顺序后 整数的最大位置
//计算出最大值和最小值
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int member : sortMembers) {
max = Math.max(member, max);
min = Math.min(member, min);
}
//定义记录每个整数 在排完序的位置
int[] counts = new int[max - min + 1];
//先统计每个整数出现的次数
for (int member : sortMembers) {
++counts[member - min];
}
//计算出每个整数 得出他的最大位置
for (int i = 1; i < counts.length; i++) {
counts[i] += counts[i - 1];
}
根据他的位置 安排放入到结果数组中
//定义一个记录排完序的数组
int[] result = new int[sortMembers.length];
//为了排序的稳定性 从右往左遍历sortMembers
for (int i = sortMembers.length - 1; i >= 0; i--) {
//找到他对应的索引
// counts[sortMembers[i] - min] - 1 记录到结果数组中
result[counts[sortMembers[i] - min] - 1] = sortMembers[i];
//索引减一
--counts[sortMembers[i] - min];
}
return result;
所以整体代码
/**
* 计数排序
*/
public class CountSort {
/**
* 计数排序实现
*
* @param sortMembers 需要排序的数组
* @return
*/
public static int[] countSort (int[] sortMembers) {
if (sortMembers.length < 2) return sortMembers;
//计算出最大值和最小值
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int member : sortMembers) {
max = Math.max(member, max);
min = Math.min(member, min);
}
//定义记录每个整数 在排完序的位置
int[] counts = new int[max - min + 1];
//先统计每个整数出现的次数
for (int member : sortMembers) {
++counts[member - min];
}
//计算出每个整数 得出他的最大位置
for (int i = 1; i < counts.length; i++) {
counts[i] += counts[i - 1];
}
//定义一个记录排完序的数组
int[] result = new int[sortMembers.length];
//为了排序的稳定性 从右往左遍历sortMembers
for (int i = sortMembers.length - 1; i >= 0; i--) {
//找到他对应的索引
// counts[sortMembers[i] - min] - 1 记录到结果数组中
result[counts[sortMembers[i] - min] - 1] = sortMembers[i];
//相对位置减一
--counts[sortMembers[i] - min];
}
return result;
}