JavaScrip通过堆实现针对对象的PriorityQueue

本文将通过最大堆实现优先队列,入队复杂度lg(n),出队复杂度lg(n)

step1:实现最大堆

大堆顶定义,每个二叉树的节点都大于左右子节点

class MaxHeap{

    //构造方法
    constructor(key) {
        this._tree=[]   //初始化数组保存数据
        this._key=key   //设置排序字段key名
    }

    //往队列里添加一个元素,复杂度O(ln(n))
    add(e){
        this._tree.push(e)  //添加对象到队列末尾
        this._adaptUp(this._tree.length-1)  //自底向上调整最大堆
    }

    //获得队首元素值,复杂度O(1)
    getFront(){
        return this._tree[0]  //返回最大堆顶元素
    }

    //获取队首元素值,并弹出队列,复杂度O(ln(n))
    extractMax(){
        //交换队尾和和队首元素,并提取队尾元素,避免队列整体移位
        let tmp=this._tree[0]
        this._tree[0]=this._tree[this._tree.length-1]
        this._tree[this._tree.length-1]=tmp
        let  _max=this._tree.pop()
        this._adaptDown(0)   //自顶向下调整最大堆
        return _max
    }

    //获得队列长度
    getSize(){
        return this._tree.length
    }

    //清空队列
    clear(){
        this._tree.clear()
    }

    //获得左节点id
    _leftChild(idx){
        return idx*2+1
    }

    //获得右节点id
    _rightChild(idx){
        return idx*2+2
    }

    //获得父节点id,“|0”可以对前边的小数取整
    _parent(idx){
        return (idx-1)/2|0
    }

    //交换队列中两个元素
    _swap(idx1,idx2){
        let  tmp=this._tree[idx1]
        this._tree[idx1]=this._tree[idx2]
        this._tree[idx2]=tmp
    }

    //自底向上使堆符合规则
    _adaptUp(idx){
        if(idx===0) return
        let parentIdx=this._parent(idx)
        while (this._tree[idx][this._key]>this._tree[parentIdx][this._key]) { //如果子节点比父节点大,则交换位置
            this._swap(idx, parentIdx)
            idx = parentIdx
            parentIdx = this._parent(idx)
        }
    }

    //自顶向下使堆符合规则
    _adaptDown(idx){
        let left=this._leftChild(idx)
        let right=this._rightChild(idx)
        let size=this.getSize()
        let maxPos=left
        while (idx<size && left<size){  //如果较大子节点大于父节点,则交换位置
            if(right<size && this._tree[left][this._key]<this._tree[right][this._key]){
                maxPos=right
            }
            if(this._tree[idx][this._key]<this._tree[maxPos][this._key]){
                this._swap(idx,maxPos)
                idx=maxPos
                left=this._leftChild(idx)
                right=this._rightChild(idx)
                maxPos=left
            }else{
                break
            }
        }
    }
}

step2:实现优先队列

class PriorityQueue{
    
    //构造方法,传入需要排序的key
    constructor(key) {
        this._data = new MaxHeap(key)
    }
    
    //获得队列长度
    getSize(){
        return this._data.getSize()
    }
    
    //获得队首对象
    getFront(){
        return this._data.getFront()
    }
    
    //弹出队首元素
    dequeue(){
        return this._data.extractMax()
    }
    
    //加入队列
    enqueue(e){
        this._data.add(e)
    }
    
    //清空队列
    clear(){
        this._data.clear()
    }
    
    //判断队列是否为空
    isEmpty(){
        return this._data.getSize()===0
    }

}

step3:例子验证

function   test1(){
    let  result=[
        {name:'李四',age:24},
        {name:'赵八',age:38},
        {name:'张三',age:13},
        {name:'王五',age:25},
        {name:'吴七',age:27}
        ]


    let  queue=new PriorityQueue("age")

    //数据加入队列
    for (let i=0;i<result.length;i++){
        queue.enqueue(result[i])
    }

    //依次弹出队首元素
    while (!queue.isEmpty()){
        let  obj=queue.dequeue()
        console.log(obj["name"]+"===="+obj["age"]+"====Queue size=="+queue.getSize())
    }

}


test1()

结果展示:

赵八====38====Queue size==4
吴七====27====Queue size==3
王五====25====Queue size==2
李四====24====Queue size==1
张三====13====Queue size==0

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值