-
堆排序
- 小根堆: L[i] <= L[2i] && L[i] <= L[2i + 1]
- 大根堆: L[i] >= L[2i] && L[i] >= L[2i + 1]
空间效率: O(1) 仅仅使用了常数个辅助单元
时间效率: O(nlog2 n)
稳定性: 不稳定
/**
* 构建大根堆
*/
function buildMaxHeap(arr) {
const len = arr.length - 1; // 因为arr[0] 暂存元素
for (let i = parseInt(len / 2); i > 0; i--) {
AdjustDown(arr, i)
}
}
/*
* 构建小根堆
*/
// 将元素i向下调整 形成大根堆
function AdjustDown(arr, k) {
const len = arr.length - 1; // 因为arr[0] 暂存元素
arr[0] = arr[k]; // arr[0] 暂存元素
for (let i = 2 * k; i <= len; i *= 2) {
if (i < len && arr[i] < arr[i + 1]) {
i++;
}
// 筛选结束 表示当前节点已经在合适的位置上, 当前节点已经大于其所有的子节点
if (arr[0] >= arr[i]) break;
// 需要交换当前节点k和i的数据元素位置
else {
arr[k] = arr[i];
k = i;
}
} // end for
arr[k] = arr[0];
}
function HeapSort(arr) {
const resultArr = [];
const len = arr.length - 1;
buildMaxHeap(arr)
for (let i = len; i >= 1; i--) {
// Swap(arr, i, 1);
// 输出堆顶部的最大元素
resultArr.push(arr[1])
const tmp = arr[i]
arr[i] = arr[1]
// 将堆底部的元素放在顶部, 重新调整构造
arr[1] = tmp;
// 这里不能用slice
arr.length = i;
AdjustDown(arr, 1)
} // end for
return resultArr;
}
function buildMaxHeap_UP(arr) {
const len = arr.length - 1; // 因为arr[0] 暂存元素
for (let i = len; i > parseInt(i / 2); i--) {
AdjustUp(arr, i);
}
}
// 向上调整 形成大根堆
function AdjustUp(arr, k) {
// var k = arr.length - 1;
arr[0] = arr[k];
let i = parseInt(k / 2);
while (i > 0 && arr[i] < arr[0]) {
arr[k] = arr[i];
k = i;
i = k / 2;
} // end while
arr[k] = arr[0];
}
const arr = [null, 53, 17, 78, 9, 45, 65, 87, 32];
// buildMaxHeap_UP(arr)
// buildMaxHeap(arr)
const resultArr = HeapSort(arr);
console.log(resultArr);
// console.log(arr.slice(1))