思路大纲
- 排序的二分位置函数(随机性)
- 交换两个下标的元素函数
- 遍历比较/交换元素的函数
- 随机的中位置换函数
- 快排函数
二分位置函数(随机)
function randomIndex(minIndex, maxIndex) {
const _min = Math.ceil(minIndex);
const _max = Math.floor(maxIndex);
return Math.floor(Math.random() * (_max - _min)) + _min;
};
交换两个下标的元素函数
function swap(arr, minIndex, maxIndex) {
[
arr[minIndex],
arr[maxIndex]
] = [
arr[maxIndex],
arr[minIndex]
];
};
遍历比较/交换元素的函数
function partition(arr, leftIndex, rightIndex) {
// 默认最右侧元素为最大,leftIndex~rightIndex中的元素都跟它比较
// 大的排前面,小的排后面
const right = arr[rightIndex];
// 哨兵位置。在leftIndex之前
// 如果完成后,index还是不变,就需要将rightIndex移动到leftIndex,说明right是最大的
let index = leftIndex - 1;
// 以leftIndex做遍历起始点,遍历leftIndex~rightIndex中间的数字
for (let i = leftIndex; i < rightIndex; i++) {
// 如果当前遍历元素,大于最大的元素
if (arr[i] > right) {
// 将哨兵位移后一位
++index;
// 将当前大的元素,移动到哨兵位
swap(arr, index, i);
}
}
const lastIndex = index + 1;
// 两种情况
// 1.rightIndex的元素是这个范围内最大的,就将rightIndex元素移动到这个范围起始位置
// 2.index到了某个位置后,就没有比right大的了,就将rightIndex移动到那个位置
swap(arr, lastIndex, rightIndex);
// 将当前移动的排序后的最大位置的坐标返回出去,供下一轮新的排序
return lastIndex;
}
随机的中位置换函数
// 只是为了需要一种随机性,不用它,对结果也是没有影响
function randomPartion(arr, leftIndex, rightIndex) {
// 获取到leftIndex~rightIndex中随机的位置
const pivot = randomIndex(leftIndex, rightIndex);
// 将随机位跟rightIndex的位置交换
swap(arr, pivot, rightIndex);
// 进行排序
return partition(arr, leftIndex, rightIndex);
}
快排函数
function randomQuickSort(heap, leftIndex, rightIndex) {
// 首先必须是两个元素及以上的数组
if (leftIndex < rightIndex) {
// 首先将当前范围的数组分成两部分排序,得到这个分离下标
const q = randomPartion(heap, leftIndex, rightIndex);
// 以分离下标的作为最大的范围继续遍历
randomQuickSort(heap, leftIndex, q - 1);
// 以分离下标最为起始范围遍历
randomQuickSort(heap, q + 1, rightIndex);
}
}
/**
* 例子: const heap = [9, 1, 0, 10, 5, 7, -1, -3, 2];
* 开始遍历时,假设当前的随机的中位下标为4,就是元素5.
* 那第一遍遍历的时候,就是将rightIndex(8) 与下标4进行交换. 5 与 2进行交换
* heap = [9, 1, 0, 10, 2, 7, -1, -3, 5];
* 第一次遍历将元素5作为最大值,排序后的数组应该为
* heap = [9, 10, 7, 5, 2, 0, -1, -3, 1]; q = 3;
* 这个时候可以清晰看到,数组被中位元素2分成了两部分,5之前的都是大于5的,5之后的都是小与5的
* left = [9, 10, 7], right = [2, 0, -1, -3, 1],这个时候不会取到5,因为5就是分隔元素
* 如果循环递归,就能得到排序后的数
*/