大顶堆实现

堆的定义

  • 堆是一颗完全二叉树
  • 堆中某个节点的值总是不大于或不小于其孩子节点的值;
  • 堆中每个节点的子树都是堆。

最大堆结构图示

堆的操作与实现

export class MaxHeap {
  constructor(data = []) {
    Array.isArray(data) && (this.data = data)
    if (typeof data === 'number') {
      this.data = new Array(data)
    }
    this.count = 0
    this.init()
  }
  init() {
    this.buildMaxHeap(this.data)
  }
  swap(arr, m, n) {
    let temp = arr[m]
    arr[m] = arr[n]
    arr[n] = temp
  }
  buildMaxHeap(data = []) {
    for (let item of data) {
      if (!item && item !== 0) return
      this.insert(item)
    }
  }
  shiftUp(k) {
    // 如果一个节点比它的父节点大(最大堆)或者小(最小堆),那么需要将它同父节点交换位置。这样是这个节点在数组的位置上升
    while (k > 0 && this.data[~~(k / 2)] < this.data[k]) {
      this.swap(this.data, ~~(k / 2), k)
      k = ~~(k / 2)
    }
  }
  shiftDown(k) {
    // 如果一个节点比它的子节点小,那么需要将它向下移动
    while (k * 2 < this.count) {
      let j = k * 2
      if (j + 1 <= this.count && this.data[j + 1] > this.data[j]) j++
      if (this.data[k] >= this.data[j]) break
      this.swap(this.data, k, j)
      k = j
    }
  }
  insert(item) {
    // 在堆的尾部添加一个新的元素,然后使用 shiftUp 来修复对。
    if (this.count + 1 > this.data.length) throw Error('超过限制长度')
    this.data[this.count] = item
    this.shiftUp(this.count)
    this.count++
  }
  extractMax() {
    //取出最大数
    if (this.count === 0) return
    const ret = this.data[0]
    this.swap(this.data, 0, --this.count)
    this.data.splice(-1)
    this.shiftDown(0)
    return ret
  }
  sort() {
    const arr = [], reset = [...this.data]
    while (this.count !== 0) {
      const item = this.extractMax(),
        index = this.count
        arr[index] = item
    }
    this.count = reset.length
    this.data = reset
    return arr
  }
}

console结果可能不准确,按F12打开控制台查看