我在 CRLS 第 3 版第 8.3 节中遇到了基数排序
这本书提供了基数排序的神秘起源。它将 MSD 版本描述为过时且棘手。它还建议 LSD 的实施。
这里我提供了一个使用这种技术的基数排序实现。
让我们从伪代码开始:
/**
* @param k: the max of input, used to create a range for our buckets
* @param exp: 1, 10, 100, 1000, ... used to calculate the nth digit
*/
Array.prototype.countingSort = function (k, exp) {
/* eslint consistent-this:0 */
/* self of course refers to this array */
const self = this;
/**
* let's say the this[i] = 123, if exp is 100 returns 1, if exp 10 returns 2, if exp is 1 returns 3
* @param i
* @returns {*}
*/
function index(i) {
if (exp)
return Math.floor(self[i] / exp) % 10;
return i;
}
const LENGTH = this.length;
/* create an array of zeroes */
let C = Array.apply(null, new Array(k)).map(() => 0);
let B = [];
for (let i = 0; i < LENGTH; i++)
C[index(i)]++;
for (let i = 1; i < k; i++)
C[i] += C[i - 1];
for (let i = LENGTH - 1; i >= 0; i--) {
B[--C[index(i)]] = this[i];
}
B.forEach((e, i) => {
self[i] = e
});
}
这是唯一棘手的部分,其余的都很简单
Array.prototype.radixSort = function () {
const MAX = Math.max.apply(null, this);
/* let's say the max is 1926, we should only use exponents 1, 10, 100, 1000 */
for (let exp = 1; MAX / exp > 1; exp *= 10) {
this.countingSort(10, exp);
}
}
下面是如何测试这个方法
let a = [589, 111, 777, 65, 124, 852, 345, 888, 553, 654, 549, 448, 222, 165];
a.radixSort()
console.log(a);
最后,正如书中提到的,这种特殊算法之所以有效,只是因为计数排序是一种就地排序算法,这意味着如果两个元素相同,则它们在输入数组中的出现顺序会被保留。