当前位置:首页 > JavaScript

js实现堆

2026-02-02 07:01:10JavaScript

堆的基本概念

堆是一种特殊的完全二叉树,分为最大堆和最小堆。最大堆的每个父节点值大于或等于子节点值,最小堆的每个父节点值小于或等于子节点值。堆常用于优先队列、堆排序等场景。

堆的数组表示

堆通常用数组表示,对于索引i的节点:

  • 父节点索引:Math.floor((i - 1) / 2)
  • 左子节点索引:2 * i + 1
  • 右子节点索引:2 * i + 2

最小堆实现代码

class MinHeap {
  constructor() {
    this.heap = [];
  }

  // 获取父节点索引
  getParentIndex(index) {
    return Math.floor((index - 1) / 2);
  }

  // 获取左子节点索引
  getLeftChildIndex(index) {
    return 2 * index + 1;
  }

  // 获取右子节点索引
  getRightChildIndex(index) {
    return 2 * index + 2;
  }

  // 交换两个节点
  swap(index1, index2) {
    [this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
  }

  // 上移操作
  shiftUp(index) {
    if (index === 0) return;
    const parentIndex = this.getParentIndex(index);
    if (this.heap[parentIndex] > this.heap[index]) {
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex);
    }
  }

  // 下移操作
  shiftDown(index) {
    const leftChildIndex = this.getLeftChildIndex(index);
    const rightChildIndex = this.getRightChildIndex(index);
    let minIndex = index;

    if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] < this.heap[minIndex]) {
      minIndex = leftChildIndex;
    }

    if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] < this.heap[minIndex]) {
      minIndex = rightChildIndex;
    }

    if (minIndex !== index) {
      this.swap(index, minIndex);
      this.shiftDown(minIndex);
    }
  }

  // 插入元素
  insert(value) {
    this.heap.push(value);
    this.shiftUp(this.heap.length - 1);
  }

  // 删除堆顶元素
  pop() {
    if (this.heap.length === 0) return null;
    const top = this.heap[0];
    const last = this.heap.pop();
    if (this.heap.length > 0) {
      this.heap[0] = last;
      this.shiftDown(0);
    }
    return top;
  }

  // 获取堆顶元素
  peek() {
    return this.heap.length > 0 ? this.heap[0] : null;
  }

  // 获取堆大小
  size() {
    return this.heap.length;
  }
}

最大堆实现代码

将最小堆的比较符号反转即可实现最大堆:

class MaxHeap {
  // ... (其他方法与MinHeap相同)

  shiftUp(index) {
    if (index === 0) return;
    const parentIndex = this.getParentIndex(index);
    if (this.heap[parentIndex] < this.heap[index]) {  // 改为小于
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex);
    }
  }

  shiftDown(index) {
    const leftChildIndex = this.getLeftChildIndex(index);
    const rightChildIndex = this.getRightChildIndex(index);
    let maxIndex = index;

    if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] > this.heap[maxIndex]) {  // 改为大于
      maxIndex = leftChildIndex;
    }

    if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] > this.heap[maxIndex]) {  // 改为大于
      maxIndex = rightChildIndex;
    }

    if (maxIndex !== index) {
      this.swap(index, maxIndex);
      this.shiftDown(maxIndex);
    }
  }
}

堆的应用示例

// 创建最小堆
const minHeap = new MinHeap();
minHeap.insert(3);
minHeap.insert(2);
minHeap.insert(1);
console.log(minHeap.pop()); // 输出1

// 创建最大堆
const maxHeap = new MaxHeap();
maxHeap.insert(1);
maxHeap.insert(2);
maxHeap.insert(3);
console.log(maxHeap.pop()); // 输出3

堆排序实现

利用堆可以实现堆排序算法:

function heapSort(arr) {
  const heap = new MinHeap();
  const sorted = [];

  // 构建堆
  for (let num of arr) {
    heap.insert(num);
  }

  // 依次取出堆顶元素
  while (heap.size() > 0) {
    sorted.push(heap.pop());
  }

  return sorted;
}

console.log(heapSort([3, 1, 4, 1, 5, 9, 2, 6])); // [1, 1, 2, 3, 4, 5, 6, 9]

js实现堆

标签: js
分享给朋友:

相关文章

js实现轮播图

js实现轮播图

基础轮播图实现 使用HTML、CSS和JavaScript实现一个简单的自动轮播图。HTML结构包含一个容器和多个图片项。 <div class="slider"> <div…

js实现计算器

js实现计算器

实现基础计算器功能 使用JavaScript创建一个基础计算器需要处理数字输入、运算符逻辑和结果显示。以下是一个简单的实现示例: let currentInput = '0'; let previ…

js 实现倒计时

js 实现倒计时

实现倒计时的基本方法 使用 JavaScript 实现倒计时可以通过 setInterval 或 setTimeout 结合日期计算来完成。以下是两种常见实现方式。 使用 setInterval 实…

js实现全选

js实现全选

实现全选功能的方法 在JavaScript中实现全选功能通常涉及监听全选复选框的点击事件,并根据其状态控制其他复选框的选中状态。以下是几种常见的实现方式: 基础DOM操作实现 通过获取所有目标复选框…

js实现全屏

js实现全屏

实现全屏的基本方法 使用JavaScript实现全屏功能主要依赖Element.requestFullscreen()方法。现代浏览器均支持此API,但不同浏览器可能需要添加前缀。 // 触发全屏…

js实现复制功能

js实现复制功能

使用 document.execCommand 方法 这种方法适用于较旧的浏览器,但在现代浏览器中可能被逐步淘汰。通过创建一个临时的 textarea 元素,将文本内容放入其中,然后执行复制命令。…