返回

JS图文讲解堆以及实现

前端

堆的数据结构

堆是一种数据结构,其中每个元素都与它的子元素之间存在某种关系。在堆中,每个元素都有一个键(key),键的值决定了该元素在堆中的位置。堆有两种类型:最大堆和小堆。

  • 在最大堆中,每个节点的值都大于或等于其子节点的值。
  • 在小堆中,每个节点的值都小于或等于其子节点的值。

堆通常用数组来实现。在数组中,堆的根节点位于数组的第一个元素,左子节点位于数组的第 2 个元素,右子节点位于数组的第 3 个元素,依次类推。

堆的操作

堆支持以下操作:

  • 插入:将一个元素插入堆中。
  • 删除:从堆中删除一个元素。
  • 查找:查找堆中最大的元素或最小的元素。
  • 合并:将两个堆合并成一个堆。

堆的应用

堆的应用非常广泛,常见的有:

  • 堆排序:堆排序是一种基于堆的数据结构的排序算法。堆排序的平均时间复杂度为 O(n log n),最坏时间复杂度为 O(n^2)。
  • 优先队列:优先队列是一种数据结构,其中元素按照其优先级排序。优先队列通常用堆来实现。
  • 第K大元素:第K大元素问题是指在给定数组中找到第K大的元素。第K大元素问题可以通过堆来解决。

堆的实现

以下是用 JavaScript 实现的堆:

class Heap {
  constructor(type) {
    this.type = type; // "max" or "min"
    this.heap = [];
  }

  insert(value) {
    this.heap.push(value);
    this.heapifyUp();
  }

  delete() {
    if (this.heap.length === 0) {
      return null;
    }

    const root = this.heap[0];
    this.heap[0] = this.heap[this.heap.length - 1];
    this.heap.pop();
    this.heapifyDown();

    return root;
  }

  find() {
    if (this.heap.length === 0) {
      return null;
    }

    return this.heap[0];
  }

  merge(otherHeap) {
    this.heap = this.heap.concat(otherHeap.heap);
    this.heapify();
  }

  heapifyUp() {
    let currentIndex = this.heap.length - 1;

    while (currentIndex > 0) {
      const parentIndex = Math.floor((currentIndex - 1) / 2);

      if (this.type === "max") {
        if (this.heap[currentIndex] > this.heap[parentIndex]) {
          [this.heap[currentIndex], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[currentIndex]];
        }
      } else if (this.type === "min") {
        if (this.heap[currentIndex] < this.heap[parentIndex]) {
          [this.heap[currentIndex], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[currentIndex]];
        }
      }

      currentIndex = parentIndex;
    }
  }

  heapifyDown() {
    let currentIndex = 0;

    while (currentIndex < this.heap.length) {
      const leftChildIndex = 2 * currentIndex + 1;
      const rightChildIndex = 2 * currentIndex + 2;

      if (this.type === "max") {
        if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] > this.heap[currentIndex]) {
          [this.heap[currentIndex], this.heap[leftChildIndex]] = [this.heap[leftChildIndex], this.heap[currentIndex]];
          currentIndex = leftChildIndex;
        } else if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] > this.heap[currentIndex]) {
          [this.heap[currentIndex], this.heap[rightChildIndex]] = [this.heap[rightChildIndex], this.heap[currentIndex]];
          currentIndex = rightChildIndex;
        } else {
          break;
        }
      } else if (this.type === "min") {
        if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] < this.heap[currentIndex]) {
          [this.heap[currentIndex], this.heap[leftChildIndex]] = [this.heap[leftChildIndex], this.heap[currentIndex]];
          currentIndex = leftChildIndex;
        } else if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] < this.heap[currentIndex]) {
          [this.heap[currentIndex], this.heap[rightChildIndex]] = [this.heap[rightChildIndex], this.heap[currentIndex]];
          currentIndex = rightChildIndex;
        } else {
          break;
        }
      }
    }
  }

  heapify() {
    for (let i = Math.floor(this.heap.length / 2) - 1; i >= 0; i--) {
      this.heapifyDown(i);
    }
  }
}

总结

堆是一种非常重要的数据结构,在计算机科学中有广泛的应用。希望通过本文,您能够对堆有更深入的了解,并能够将其应用到您的项目中。