当前位置:首页 > JavaScript

js实现堆

2026-04-07 00:19:40JavaScript

堆的基本概念

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

js实现堆

最大堆实现

以下是用JavaScript实现最大堆的完整代码示例:

js实现堆

class MaxHeap {
  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]];
  }

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

  heapifyUp() {
    let index = this.heap.length - 1;
    while (index > 0) {
      const parentIndex = this.getParentIndex(index);
      if (this.heap[parentIndex] >= this.heap[index]) break;
      this.swap(parentIndex, index);
      index = parentIndex;
    }
  }

  extractMax() {
    if (this.heap.length === 0) return null;
    const max = this.heap[0];
    const last = this.heap.pop();
    if (this.heap.length > 0) {
      this.heap[0] = last;
      this.heapifyDown();
    }
    return max;
  }

  heapifyDown() {
    let index = 0;
    const length = this.heap.length;
    while (true) {
      const leftChildIndex = this.getLeftChildIndex(index);
      const rightChildIndex = this.getRightChildIndex(index);
      let largestIndex = index;

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

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

      if (largestIndex === index) break;
      this.swap(index, largestIndex);
      index = largestIndex;
    }
  }

  peek() {
    return this.heap.length > 0 ? this.heap[0] : null;
  }

  size() {
    return this.heap.length;
  }
}

最小堆实现

最小堆的实现与最大堆类似,只需调整比较逻辑:

class MinHeap {
  // 构造函数和方法与MaxHeap相同

  heapifyUp() {
    let index = this.heap.length - 1;
    while (index > 0) {
      const parentIndex = this.getParentIndex(index);
      if (this.heap[parentIndex] <= this.heap[index]) break;
      this.swap(parentIndex, index);
      index = parentIndex;
    }
  }

  heapifyDown() {
    let index = 0;
    const length = this.heap.length;
    while (true) {
      const leftChildIndex = this.getLeftChildIndex(index);
      const rightChildIndex = this.getRightChildIndex(index);
      let smallestIndex = index;

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

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

      if (smallestIndex === index) break;
      this.swap(index, smallestIndex);
      index = smallestIndex;
    }
  }

  extractMin() {
    // 同extractMax
  }
}

堆的应用示例

堆排序算法的实现:

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

  // 构建堆
  arr.forEach(num => heap.insert(num));

  // 依次提取最大值
  while (heap.size() > 0) {
    sorted.unshift(heap.extractMax());
  }

  return sorted;
}

// 使用示例
const unsorted = [3, 1, 4, 1, 5, 9, 2, 6];
const sorted = heapSort(unsorted);
console.log(sorted); // [1, 1, 2, 3, 4, 5, 6, 9]

性能分析

堆的插入和删除操作时间复杂度均为O(log n),构建堆的时间复杂度为O(n),堆排序的时间复杂度为O(n log n)。空间复杂度为O(1)(原地排序)或O(n)(非原地实现)。

标签: js
分享给朋友:

相关文章

js实现轮播

js实现轮播

实现轮播图的基本思路 轮播图的核心逻辑是通过定时切换展示的图片或内容,通常结合左右滑动按钮和指示器(小圆点)增强交互性。以下是基于原生JavaScript的实现方法。 HTML结构 构建轮播图的HT…

js实现继承

js实现继承

原型链继承 通过将子类的原型指向父类的实例实现继承。子类实例可以访问父类原型上的属性和方法。 function Parent() { this.name = 'parent'; } Parent…

js 实现继承

js 实现继承

原型链继承 通过让子类的原型对象指向父类的实例来实现继承。子类实例可以访问父类原型上的属性和方法。 function Parent() { this.name = 'parent'; } Par…

js实现类

js实现类

JavaScript 实现类的几种方式 JavaScript 是一种基于原型的语言,但在 ES6 之后引入了 class 语法糖,使得实现类更加直观。以下是几种常见的实现方式: 使用构造函数 传统的…

js实现瀑布流

js实现瀑布流

实现瀑布流布局 瀑布流布局是一种常见的网页布局方式,常用于图片展示、商品列表等场景。以下是使用 JavaScript 实现瀑布流布局的几种方法。 纯 JavaScript 实现 通过计算元素的位置和…

js实现路由

js实现路由

js实现路由的方法 在JavaScript中实现路由功能可以通过多种方式完成,以下是几种常见的方法: 使用原生JavaScript实现路由 通过监听window.onhashchange事件来实现基…