适用范围与背景
前几天写了,计数排序,刚好学习基数排序,我认为基数排序是计数排序的一个补充或者说延伸,因为计数排序不适合,数列元素间差值较大的情况,而基数排序就解决了此情况,它适用于大整数排序。
算法思想
不像传统排序算法,两个元素间相互比较大小,进行排序,而是通过数列索引天然有序的特性来排序。
一图胜千言:
每一位的比较,都保留了上一次比较的结果,例如说: 当比较百位时, 那么前两个次 ,个位,和十位的比较的结果不会被破坏,可以看第三列,的结果所有百位以下的数字,是有序的。
核心代码
@Test
public void cardinalitySort() {
int[] arr = {2, 117, 1, 80, 0, 1114, 18, 218, 316, 2113, 3, 81, 4};
// 1 求出最大的
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
for (int i = 1; max / i > 0; i *= 10) {
cardinalitySort(arr, i);
}
System.out.println("最终结果"+Arrays.toString(arr));
}
/**
* @param arr
* @param exp 指数, 例如 1 10 100 1000
*/
private void cardinalitySort(int[] arr, int exp) {
int[] bucket = new int[10];
// 每一次 提取 个 十 百 (arr[j] / i)%1
for (int j = 0; j < arr.length; j++) {
bucket[(arr[j] / exp) % 10]++;
}
// 变成一个排名数组
for (int j = 1; j < bucket.length; j++) {
bucket[j] += bucket[j - 1];
}
// temp sort result
int[] rs = new int[arr.length];
/**
* 这里一定是 倒序遍历,否则会破坏上一次结果,原因:例如,当比较十位时,那么小于10
* 的数字排名都是并列第一。
* 所以要为这些并列第一的在排序, 所以从数列后面遍历
**/
for (int j = arr.length-1; j >=0; j--) {
rs[bucket[(arr[j] / exp) % 10] - 1] = arr[j];
bucket[(arr[j] / exp) % 10]--;
}
for (int i = 0; i < arr.length; i++) {
arr[i] =rs[i];
}
}
我觉的如果没有写过计数排序的同学,挺难理解上面代码里说的排名数组那块的代码,建议先看下我之前写的计数排序动漫与代码 几分钟的一篇小博文
赠人玫瑰,手有余香,你的点赞,我的动力!
如果你能看到这里了,不如点赞关注一下,我会认真分享每一篇博文。大家共同成长。
我的公众号:茄子的笔记
更多分享可见: