优先队列/堆的基础

优先队列(堆)的定义和性质

定义:
优先队列: 特殊的“队列”,取出元素的顺序是按照它的优先级大小,而不是元素进入队列的先后顺序。

使用堆来实现优先队列。
性质:

  1. 结构性:用数组表示的完全二叉树。
  2. 有序性:任一结点是其子树所有结点的最大值(或最小值)。
    最大堆:maxHeap,也叫大顶堆
    最小堆:minHeap,也叫小顶堆
  3. 从根结点到任意结点的路径上,都是有序的。

基础操作

下面以大顶堆为例进行说明

1.初始化
  • 堆可以用数组实现
  • 数组的第0个元素可以作为“哨兵”,不存储实际使用的值,用来简化堆中的一些操作。比如存一个后面结点永远比它小的值(MAX_VALUE),这样可以方便后面的插入操作。

init

2. 插入
  1. 在数组后面插入新值
  2. 从新值从下往上进行调整,只要它比父结点大,父结点就往下移动;否则停止,将该值放到对应的位置

insert

3.删除堆顶元素(删除最大值)
  1. 记录堆顶元素。
  2. 将堆的最后一个元素放到堆顶。然后进行堆的调整。
  3. 从根结点开始,取它的左右子节点的最大值,看子节点是否比它大,如果子节点更大,将子节点往上移动,然后再看子节点的左右子节点,直到叶子节点或者左右子节点比该值小。

deleteMax

4.堆的构建

方式一: 循环插入 O(N*logN),将元素一个一个插入初始为空的堆中。
方式二:首先将N个元素顺序存入数组,先满足完全二叉树的性质;然后再从n/2的位置开始调整堆,使之符合有序性。每次调整都是 左右两个子树原本都是堆,然后将根结点进行调整。类似于删除最大元素之后的调整。时间复杂度O(n)。

/*----------- 建造最大堆 -----------*/
void PercDown( MaxHeap H, int p )
{ /* 下滤:将H中以H->Data[p]为根的子堆调整为最大堆 */
    int Parent, Child;
    ElementType X;
 
    X = H->Data[p]; /* 取出根结点存放的值 */
    for( Parent=p; Parent*2<=H->Size; Parent=Child ) {
        Child = Parent * 2;
        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
            Child++;  /* Child指向左右子结点的较大者 */
        if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
        else  /* 下滤X */
            H->Data[Parent] = H->Data[Child];
    }
    H->Data[Parent] = X;
}
 
void BuildHeap( MaxHeap H )
{ /* 调整H->Data[]中的元素,使满足最大堆的有序性  */
  /* 这里假设所有H->Size个元素已经存在H->Data[]中 */
    int i;
    /* 从最后一个结点的父节点开始,到根结点1 */
    for( i = H->Size/2; i>0; i-- )
        PercDown( H, i );
}

计算时间复杂度

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值