1
堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;
由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。
这种数据结构具有以下性质。
任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。堆总是一棵完全树。
即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
常见的堆有二叉堆、斐波那契堆等。 

解释

以上是 维基百科 关于堆的描述,转换为人话就是大概这么几条:

  • 堆在本质上是一种二叉树
  • 但是它是用数组的形式来描述二叉树
  • 按照二叉树的每一排依次进行序号的排序
  • 且堆在非最后子叶的情况下不能只有一个元素
  • 对序号为 k 的节点 它的左节点序号2k+1 它的右节点序号2k+2 它的父节点的序号是k/2向下取整

如下图所示,由上至下 每一行按照序号进行排序 形成一个数组
[100, 19, 36, 17, 3, 25, 1, 2, 7]

关于 且堆在非最后子叶的情况下不能只有一个元素 的解释是:
根据图中的树节点,如果有最后的27节点, 那么 36节点不能只有一个节点, 必须有两个节点, 这样才能保证堆序号的连续性和正确性

图片.png

除此之外, 堆还分为:

  • 最大堆

    • 父节点总大于子节点
    • 顶部是最大值
  • 最小堆

    • 父节点总小于子节点
    • 顶部是最小值
堆的操作
  • 堆化

最大堆化 max-heapify

维护最大堆性质的过程 和子节点不断比较最大值和自己交换

最小堆化 min-heapify

维护最小堆性质的过程
JS建堆并实现最大堆化
class MaxHeap {
    constructor(data, max=10000){
        this.list = new Array(max) // 堆的最大值
        for(let i = 0; i < data.length; i++){
            this.list[i] = data[i]
        }
        this.heap_length = data.length; // 堆中真实元素个数
        this.build(); // 开始建堆
    }
    
    build(){
        // 首先获取最后一个元素的序号/索引
        // 注意向上取整
        let IND = Math.floor(this.heap_length / 2) + 1;
        while(IND >= 0){
            this.max_heapify(IND--) // 树形结构 由下往上
        }
    }
    
    max_heapify(index){
        // 默认index为父级序号
        let parent_ind = index
        // 获取最大子元素序号 先默认左子元素为最大
        let max_child_ind = parent_ind * 2 + 1
        
        while(max_child_ind <= this.heap_length - 1){
            // 判断1: 子与子的大小关系
            if(
                max_child_ind < this.heap_length - 1 &&
                this.list[max_child_ind] < this.list[max_child_ind + 1]
            ){
                // 如果左子元素小于右子元素 将最大序号指向右子元素
                max_child_ind = max_child_ind + 1
            }
            
            // 判断2: 判断子与父的大小关系
            if(this.list[parent_ind] >= this.list[max_child_ind]){
                // 如果本身父元素就大于子元素 不做处理 直接break
                break;
            }else{
                // 父元素小于子元素 将父元素与子元素进行交换
                let temp = this.list[parent_ind];
                this.list[parent_ind] = this.list[max_child_ind];
                this.list[max_child_ind] = temp
            }
        }
        
    }
    
}

测试一下:

const data = [12, 15, 2, 4, 3, 8, 7, 6, 5];

const test = new MaxHeap(data);
console.log(test);


// 打印结果:
MaxHeap {
  list: [ 15, 12, 8, 6, 3, 2, 7, 4, 5, <9991 empty items> ],
  heap_length: 9
}

即,满足了最大堆化


Funky_Tiger
443 声望33 粉丝

刷题,交流,offer,内推,涨薪,相亲,前端资源共享...