数据结构之堆

概念

堆是一种特殊的完全二叉树

所有节点都大于等于(最大堆)或小于等于(最小堆)它的子节点

Js中通常用数组表示堆,左侧子节点的位置是2*index+1,右侧子节点的位置是2*index+2

父节点的位置是(index-1)/2

JS类构建最小堆

class minHeap {
    constructor(){
        this.heap=[];
    }
    swap(i1,i2){
        let temp=this.heap[i1];
        this.heap[i1]=this.heap[i2];
        this.heap[i2]=temp;
    }
    getParentIndex(i){
    return (i-1)/2
    }
    getLeftIndex(i){
        return i*2+1
    }
    getRightIndex(i){
        return i*2+2
    }
    shiftUp(index){
      if(index==0){return}
      let parentIndex=getParentIndex(index);
      if(this.heap[index]<this.heap[parentIndex]){
          this.swap(index,parentIndex);
          this.shiftUp(parentIndex);
      }}
    shiftDown(index){
        let leftIndex=this.getLeftIndex(index);
        let rightIndex=this.getRightIndex(index);
        if(this.heap[leftIndex]<this.heap[index]){
            this.swap(index,leftIndex);
            this.shiftDown(leftIndex);
        }
        if(this.heap[rightIndex]<this.heap[index]){
            this.swap(index,rightIndex);
            this.shiftDown(rightIndex);
        }
    }
    insertValue(value){
        this.heap.push(value);
        this.shiftUp(this.heap.length-1);
    }
    pop(value){
        this.heap[0]=this.heap.pop();
        shiftDown(0);
    }
    peak(){
        return this.heap[0];
    }
    size(){
        return this.heap.length
    }
}
const h=new minHeap();
h.insertValue(2);
h.insertValue(1);
h.insertValue(6);
h.insertValue(5);
h.insertValue(4);
h.insertValue(3);
h.pop();
h.peak();
h.size();
console.log(h.heap);

最小堆求解数组中最大的第k个元素

class minHeap {
    constructor(){
        this.heap=[];
    }
    swap(i1,i2){
        let temp=this.heap[i1];
        this.heap[i1]=this.heap[i2];
        this.heap[i2]=temp;
    }
    getParentIndex(i){
    return  Math.floor((i-1)/2)
    }
    getLeftIndex(i){
        return i*2+1
    }
    getRightIndex(i){
        return i*2+2
    }
    shiftUp(index){
      if(index==0){return}
      let parentIndex=this.getParentIndex(index);
      if(this.heap[index]<this.heap[parentIndex]){
          this.swap(index,parentIndex);
          this.shiftUp(parentIndex);
      }}
    shiftDown(index){
        let leftIndex=this.getLeftIndex(index);
        let rightIndex=this.getRightIndex(index);
        if(this.heap[leftIndex]<this.heap[index]){
            this.swap(index,leftIndex);
            this.shiftDown(leftIndex);
        }
        if(this.heap[rightIndex]<this.heap[index]){
            this.swap(index,rightIndex);
            this.shiftDown(rightIndex);
        }
    }
    insertValue(value){
        this.heap.push(value);
        this.shiftUp(this.heap.length-1);
    }
    pop(value){
        this.heap[0]=this.heap.pop();
        this.shiftDown(0);
    }
    peak(){
        return this.heap[0];
    }
    size(){
        return this.heap.length
    }
}
var findKthLargest = function(nums, k) {
     const h=new minHeap();
     nums.forEach(n=>{
         h.insertValue(n);
         if(h.size()>k){
             h.pop();
         }     });
     return h.peak()
};

前k个高频元素

var topKFrequent = function(nums, k) {
    let map=new Map();
    nums.forEach(n=>{
        map.set(n,map.has(n)? map.get(n)+1:1)
    });
    let arr=Array.from(map).sort((a,b)=> b[1]-a[1]);
    return arr.slice(0,k).map(n=>n[0])
};

合并K个排序链表

class minHeap {
    constructor(){
        this.heap=[];
    }
    swap(i1,i2){
        let temp=this.heap[i1];
        this.heap[i1]=this.heap[i2];
        this.heap[i2]=temp;
    }
    getParentIndex(i){
    return  Math.floor((i-1)/2)
    }
    getLeftIndex(i){
        return i*2+1
    }
    getRightIndex(i){
        return i*2+2
    }
    shiftUp(index){
      if(index==0){return}
      let parentIndex=this.getParentIndex(index);
      if(this.heap[parentIndex]&&this.heap[index].val<this.heap[parentIndex].val){
          this.swap(index,parentIndex);
          this.shiftUp(parentIndex);
      }}
    shiftDown(index){
        let leftIndex=this.getLeftIndex(index);
        let rightIndex=this.getRightIndex(index);
        if(this.heap[leftIndex]&&this.heap[leftIndex].val<this.heap[index].val){
            this.swap(index,leftIndex);
            this.shiftDown(leftIndex);
        }
        if(this.heap[rightIndex]&&this.heap[rightIndex].val<this.heap[index].val){
            this.swap(index,rightIndex);
            this.shiftDown(rightIndex);
        }
    }
    insertValue(value){
        this.heap.push(value);
        this.shiftUp(this.heap.length-1);
    }
    pop(value){
        if(this.size()===1)return this.heap.shift()
        const top =this.heap[0];
        this.heap[0]=this.heap.pop();
        this.shiftDown(0);
        return top
    }
    peak(){
        return this.heap[0];
    }
    size(){
        return this.heap.length
    }
}
var mergeKLists = function(lists) {
    let list=new ListNode(0);
    let p=list;
    let h=new minHeap();
    lists.forEach(n=>{if(n)h.insertValue(n)});
    while(h.size()){
        let n=h.pop();
        p.next=n;
        p=p.next;
        if(n.next){h.insertValue(n.next);}
    }
    return list.next
};

总结

堆能快速高效地找出最大值和最小值

找出第k个最大(小)的元素可以用堆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值