我真的想过这个问题。所以首先我找到了正常的搜索模式并写了。
let QuickSort = (arr, low, high) => {
if (low < high) {
p = Partition(arr, low, high);
QuickSort(arr, low, p - 1);
QuickSort(arr, p + 1, high);
}
return arr.A;
}
let Partition = (arr, low, high) => {
let pivot = arr.A[high];
let i = low;
for (let j = low; j <= high; j++) {
if (arr.A[j] < pivot) {
[arr.A[i], arr.A[j]] = [arr.A[j], arr.A[i]];
i++;
}
}
[arr.A[i], arr.A[high]] = [arr.A[high], arr.A[i]];
return i;
}
let arr = { A/* POINTER */: [33, 22, 88, 23, 45, 0, 44, 11] };
let res = QuickSort(arr, 0, arr.A.length - 1);
console.log(res);
结果是[0, 11, 22, 23, 33, 44, 45, 88]
但它不稳定;所以我检查了其他答案,@6502 的想法对我来说很有趣,“两个项目不必相同”才能区分。
好吧,我有一个解决方案,但它不是最佳的。我们可以将项目的索引保存在一个单独的数组中。 在这个想法中,内存消耗几乎会翻倍。
arr.A => 数字数组
arr.I => A的每一项相关的索引
influencer => 这应该是一个非常非常小的数字;我想以此作为区分相似项目的一个因素。
所以我们可以这样改变分区:
let Partition = (arr, low, high) => {
let pivot = arr.A[high];
let index = arr.I[high];
let i = low;
for (let j = low; j <= high; j++) {
if (arr.A[j] + (arr.I[j] * influencer) < pivot + (index * influencer)) {
[arr.A[i], arr.A[j]] = [arr.A[j], arr.A[i]];
[arr.I[i], arr.I[j]] = [arr.I[j], arr.I[i]];
i++;
}
}
[arr.A[i], arr.A[high]] = [arr.A[high], arr.A[i]];
[arr.I[i], arr.I[high]] = [arr.I[high], arr.I[i]];
return i;
}
let influencer = 0.0000001;
let arr = {
I/* INDEXES */: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
A/* POINTER */: [33, 22, 88, 33, 23, 45, 33, 89, 44, 11]
};
let res = QuickSort(arr, 0, arr.A.length - 1);
console.log(res);
结果:
I: [19, 11, 14, 10, 13, 16, 18, 15, 12, 17],
A: [11, 22, 23, 33, 33, 33, 44, 45, 88, 89]