思路大纲
- 排序的二分位置函数(随机性)
- 交换两个下标的元素函数
- 遍历比较/交换元素的函数
- 随机的中位置换函数
- 快排函数
二分位置函数(随机)
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就是分隔元素* 如果循环递归,就能得到排序后的数*/