js 算法-最小堆、最大堆

一、最小堆

1、结构特性:完全二叉树(所有层除最后一层外均填满)
2、堆序特性:父节点值 ≤ 子节点值
3、操作时间复杂度:插入/删除 O(log n),取最小值 O(1)

// 最小二叉堆
class MinHeap{
  constructor(){
    this.heap = []
  }
  // 添加元素
  insert(val) {
    this.heap.push(val)
    this.up(this.heap.length-1)
  }
  // 上(前)移动
  up(index) {
    if(index===0) return;
    const parentIndex = this.getParentIndex(index);
    if(this.heap[parentIndex]>this.heap[index]){
      this.swap(parentIndex,index)
      this.up(parentIndex)
    }
  }
  // 下(后)移动
  down(index) {
    if(index>=this.heap.length) return ;
    const leftIndex = this.getLeftIndex(index)
    const rightndex = this.getRightIndex(index)
    if(leftIndex < this.heap.length && this.heap[index]>this.heap[leftIndex]){
      this.swap(leftIndex,index)
      this.down(leftIndex)
    }
    if(rightndex < this.heap.length && this.heap[index]>this.heap[rightndex]) {
      this.swap(rightndex,index)
      this.down(rightndex)
    }
  }
  // 交换位置
  swap(i1,i2){
    const temp = this.heap[i1]
    this.heap[i1] = this.heap[i2]
    this.heap[i2] = temp
  }
  // 删除堆顶
  pop() {
    this.heap[0] = this.heap.pop();
    this.down(0)
  }
  // 获取堆顶
  peek(){
    return this.heap[0]
  }
  size(){
    return this.heap.length
  }
  // 获取父级节点-index
  getParentIndex(index) {
    return Math.floor((index -1) /2 );
  }
  // 获取左侧子节点-index
  getLeftIndex(index) {
    return index * 2 + 1
  }
  // 获取右侧子节点-index
  getRightIndex(index) {
    return index * 2 + 2
  }
}

应用场景:
优先队列实现
Dijkstra 最短路径算法
求 Top K 小元素(结合最大堆)
堆排序(修改为最大堆)

二、最大堆

1、结构特性:完全二叉树(所有层除最后一层外均填满)
2、堆序特性:父节点值 ≥子节点值

// 最大堆
class MaxHeap {
    constructor() {
      this.heap = [];
    }
  
    // 获取父节点索引(与最小堆相同)
    _parentIndex(index) {
      return Math.floor((index - 1) / 2);
    }
  
    // 交换元素(与最小堆相同)
    _swap(i, j) {
      [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
    }
  
    // 插入元素(逻辑相同,但比较方向改变)
    insert(value) {
      this.heap.push(value);
      this._bubbleUp(this.heap.length - 1);
    }
  
    // 上浮调整(关键修改点:将 < 改为 >)
    _bubbleUp(index) {
      while (index > 0) {
        const parentIndex = this._parentIndex(index);
        if (this.heap[index] <= this.heap[parentIndex]) break; // 比较方向反转
        this._swap(index, parentIndex);
        index = parentIndex;
      }
    }
  
    // 提取最大值(原extractMin改名)
    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._sinkDown(0);
      }
      return max;
    }
  
    // 下沉调整(关键修改点:选择更大的子节点)
    _sinkDown(index) {
      const leftChild = 2 * index + 1;
      const rightChild = 2 * index + 2;
      let largest = index; // 变量名改为largest
  
      if (leftChild < this.heap.length && 
          this.heap[leftChild] > this.heap[largest]) { // 比较方向反转
        largest = leftChild;
      }
  
      if (rightChild < this.heap.length && 
          this.heap[rightChild] > this.heap[largest]) { // 比较方向反转
        largest = rightChild;
      }
  
      if (largest !== index) {
        this._swap(index, largest);
        this._sinkDown(largest);
      }
    }
  
    // 其他方法保持不变
    size() {
      return this.heap.length;
    }
  
    peek() {
      return this.heap[0] ?? null;
    }
  }

应用场景:
优先队列(高优先级先出)
Top K 大元素问题(结合最小堆)
堆排序算法(升序排序)
滑动窗口最大值(特殊场景优化)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值