【算法】堆排序
2024/04/08 11:52:38
堆排序
堆在存储形式上和完全二叉树的层序遍历一样
50
45 40
20 25 35 30
10 15
对堆中的节点按层进行编号,映射到数组中为:
[50, 45, 40, 20, 25, 35, 30, 10 15]
这样存储的堆有如下特点:
- 第 n 个元素的 左子节点 为 2*n+1
- 第 n 个元素的 右子节点 为 2*n+2
- 第 n 个元素的 父节点 为 Math.floor((n-1)/2)
- 最后一个非叶子节点为 Math.floor(arr.length/2)-1
算法题目
- 215.数组中的第 k 个最大元素.js
var findKthLargest = function (nums, k) {
let heapSize = nums.length;
buildMaxHeap(nums, heapSize); // 构建好了一个大顶堆
// 进行下沉 大顶堆是最大元素下沉到末尾
for (let i = nums.length - 1; i >= nums.length - k + 1; i--) {
swap(nums, 0, i);
--heapSize; // 下沉后的元素不参与到大顶堆的调整
// 重新调整大顶堆
maxHeapify(nums, 0, heapSize);
}
return nums[0];
// 自下而上构建一颗大顶堆
function buildMaxHeap(nums, heapSize) {
for (let i = Math.floor(heapSize / 2) - 1; i >= 0; i--) {
maxHeapify(nums, i, heapSize);
}
}
// 从左向右,自上而下的调整节点
function maxHeapify(nums, i, heapSize) {
let l = i * 2 + 1;
let r = i * 2 + 2;
let largest = i;
if (l < heapSize && nums[l] > nums[largest]) {
largest = l;
}
if (r < heapSize && nums[r] > nums[largest]) {
largest = r;
}
if (largest !== i) {
swap(nums, i, largest); // 进行节点调整
// 继续调整下面的非叶子节点
maxHeapify(nums, largest, heapSize);
}
}
function swap(a, i, j) {
let temp = a[i];
a[i] = a[j];
a[j] = temp;
}
};