计数排序:很强就对了,它的性能比系统API的多线程或单线程排序都快!不过有个前提,就是数据量,不要超过达到 1千万使用计数排序,测试过,性能会比系统API慢,不过也得看数据复杂度对比,一般API并排比计排1千万数据快。
如果max 和 min 只有两个,差值又大,计数排序就很亏,创建的计数数组也就大了
去重版的计数排序很好用
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr1 = {99, 88, -77, -77, 99, -66, 55, 44, 33, -22, 11};
int[] arr2 = arr1.clone();
countSort(arr1);
arr2 = countSort2(arr2);
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
}
// 正常计数排序版本
public static void countSort(int[] arr) {
// 打擂台,找到最大与最小值
int max = arr[0];
int min = arr[0];
for (int i = 1; i < arr.length; ++i) {
if (arr[i] > max) max = arr[i];
if (arr[i] < min) min = arr[i];
}
// 创建一个计数长度数组
int[] counts = new int[max - min + 1]; // +1 是 max - min 后,得到起本身,也就是 min = 0 时,数组本身从 0 开始,避免这个 bug
// 计数
for (int i = 0; i < arr.length; ++i) ++counts[arr[i] - min];
// 排序
for (int i = 0, len = 0; i < counts.length; ++i) {
while (counts[i] > 0) { //当前位置计数的个数,也就是有可能一个数重复
arr[len++] = min + i; //最小值 + 索引位置 = 精确数
--counts[i];
}
}
}
// 去重复版计数排序
public static int[] countSort2(int[] arr) {
// 打擂台,找到最大与最小值
int max = arr[0];
int min = arr[0];
for (int i = 1; i < arr.length; ++i) {
if (arr[i] > max) max = arr[i];
if (arr[i] < min) min = arr[i];
}
// 创建一个计数长度数组
int[] counts = new int[max - min + 1]; // +1 是 max - min 后,得到起本身,也就是 min = 0 时,数组本身从 0 开始,避免这个 bug
// 计数
for (int i = 0; i < arr.length; ++i) ++counts[arr[i] - min];
// 排序 + 去重,也就是把 while 换成 if
int len = 0;
for (int i = 0; i < counts.length; ++i) {
if (counts[i] > 0) { //当前位置有数
arr[len++] = min + i; //最小值 + 索引位置 = 精确数
--counts[i];
}
}
// 拷贝数组
if (len != arr.length) {
int[] newArr = new int[len];
System.arraycopy(arr, 0, newArr, 0, len);
arr = newArr;
}
return arr;
}
}
输出:
[-77, -77, -66, -22, 11, 33, 44, 55, 88, 99, 99]
[-77, -66, -22, 11, 33, 44, 55, 88, 99]