📜  数据结构|堆|问题11(1)

📅  最后修改于: 2023-12-03 14:54:56.647000             🧑  作者: Mango

数据结构 | 堆 | 问题11

简介

在数据结构中,堆是一种特殊的树形数据结构,通常用来实现优先队列。堆有常见的两种形式:最大堆和最小堆。最大堆的性质是每个节点都大于或等于其子节点,最小堆则是每个节点都小于或等于其子节点。

问题11需要我们实现一个最小堆,其中需要包含以下几个操作:

  • build():将任意数组构建成最小堆;
  • insert(value):在最小堆中插入一个元素;
  • remove():删除最小堆的根节点;
  • getMin():获取最小堆的根节点元素。
实现

我们可以用数组来实现一个最小堆,其中下标i的左右子节点下标分别为2i+1和2i+2,父节点下标为floor((i-1)/2)。具体实现如下:

class MinHeap {
  constructor() {
    this.heap = [];
  }
  build(arr) {
    this.heap = arr;
    for (let i = Math.floor(arr.length / 2) - 1; i >= 0; i--) {
      this.heapifyDown(i);
    }
  }
  insert(value) {
    this.heap.push(value);
    this.heapifyUp(this.heap.length - 1);
  }
  remove() {
    if (this.heap.length === 0) {
      return null;
    }
    if (this.heap.length === 1) {
      return this.heap.pop();
    }
    const root = this.heap[0];
    this.heap[0] = this.heap.pop();
    this.heapifyDown(0);
    return root;
  }
  getMin() {
    return this.heap.length > 0 ? this.heap[0] : null;
  }
  heapifyUp(index) {
    let parent = Math.floor((index - 1) / 2);
    while (index > 0 && this.heap[index] < this.heap[parent]) {
      this.swap(index, parent);
      index = parent;
      parent = Math.floor((index - 1) / 2);
    }
  }
  heapifyDown(index) {
    let left = 2 * index + 1;
    let right = 2 * index + 2;
    let smallest = index;
    if (left < this.heap.length && this.heap[left] < this.heap[smallest]) {
      smallest = left;
    }
    if (right < this.heap.length && this.heap[right] < this.heap[smallest]) {
      smallest = right;
    }
    if (smallest !== index) {
      this.swap(index, smallest);
      this.heapifyDown(smallest);
    }
  }
  swap(i, j) {
    [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
  }
}
示例
const minHeap = new MinHeap();
minHeap.build([4, 1, 3, 2, 16, 9, 10, 14, 8, 7]);
minHeap.insert(0);
console.log(minHeap.getMin()); // 0
console.log(minHeap.remove()); // 0
console.log(minHeap.getMin()); // 1
总结

最小堆是一个非常有用的数据结构,它可以帮助我们高效地解决排名、选择、排序等问题。在实现最小堆时,需要注意堆化操作的顺序以及边界条件的判断。如果你想进一步了解最小堆,可以通过LeetCode上的相关题目进行练习和掌握。