【ADT】二叉堆

结构

Javascript没有堆这个数据结构,需要自己实现一个,实现原理是 用一个线性表存储一棵完全二叉树,并依照堆的ADT实现即可:

已知索引为i的结点,求
(1)双亲节点索引? idx/2 || undefined
(2)左孩子节点索引?2*idx+1 || undefined
(3)右孩子节点索引?2*idx+1 || undedined

堆的ADT
(from visualgo)

优先队 (PQ) 抽象数据结构 (ADT) 和普通的队列 ADT 差不多, 但是它多了以下两个主要操作:

insert(x): 放一个新元素 (键值) x 进去优先队 (相同顺序),
y = extract(): 返回已经在优先队里的有着最高优先级(键值)的元素 y 如果存在并列情况,返回先入队的那个。
也就是说像一个正常的 Queue 那样 先进先出(FIFO)

一个小根堆实现如下:

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

    // 获取左叶子索引
    getLeftIndex(idx) {
        return 2*idx + 1;
    }

    // 获取右叶子索引
    getRightIndex(idx) {
        return 2*idx+2;
    }

    // 获取双亲叶子索引
    getParentIndex(idx) {
        if(idx === 0) return undefined;
        return Math.floor((idx-1)/2);
    }

    // 建堆操作:插入
    insert(val) {
        if(val != null) {
            this.heap.push(val);
            this.siftUp(this.heap.length - 1);
            return true;
        }
        return false;
    }

    // 建堆操作:上移
    siftUp(idx) {
        let parent = this.getParentIndex(idx);
        while(idx>0 && this.heap[parent] > this.heap[idx]) {
            let tmp = this.heap[parent];
            this.heap[parent] = this.heap[idx];
            this.heap[idx] = tmp;
            idx = parent;
            parent = this.getParentIndex(idx);
        }
    }

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

    // 判断是否为空堆
    isEmpty() {
        return this.size() === 0;
    }

    // 获取堆顶元素
    findMinimum() {
        return this.isEmpty() ? undefined : this.heap[0];
    }

    // 导出操作
    extract() {
        if(this.isEmpty()) return undefined;
        if(this.size() === 1) return this.heap.shift();
        const removeValue = this.heap.shift();
        this.siftDown(0);
        return removeValue;
    }

    // 调整堆:下移
    siftDown(idx) {
        let element = idx;
        const left = this.getLeftIndex(idx);
        const right = this.getRightIndex(idx);
        const size = this.size();
        if(left < size && this.heap[element] > this.heap[left]) element = left;
        if(right < size && this.heap[element] > this.heap[right]) element = right;
        if(idx != element) {
            let tmp = this.heap[idx];
            this.heap[idx] = this.heap[element];
            this.heap[element] = tmp;
            this.siftDown(element);
        }
    }
}

使用

(1)1834 单线程 CPU
(2)40. 最小的k个数
(3)215. 数组中的第K个最大元素
(4)42. 接雨水
(5)“Top” k 题型总结ing:
“Top” k - 1: leetcode 215
“Top” k - 2: 面试题17.14
“Top” k - 3: leetcode 973
“Top” k - 4: leetcode 1167
“Top” k - 5: leetcode 347
“Top” k - 6: leetcode 451
(6)767 重构字符串

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值