数据结构—完全二叉堆

1. 简介

  • 完全二叉堆可用于实现优先队列

  • 当然,使用数组或列表也可以实现优先队列,但通常需要先将其中的所有数据进行排序才可,即首先维护一种全序关系。

  • 但事实上,优先队列只要能够确定全局优先级最高的 entry 即可,而不要求全局先有序。

  • 完全二叉堆无需先对所有数据进行排序即可确定全局优先级最高的 entry,因此更加适用于优先队列的实现。

2. 定义

  • 结构性:完全二叉堆的逻辑结构就是一棵完全二叉树,但堆可以使用数组来实现。

  • 堆序性:对于最小堆来说,堆中每个父节点都要小于等于其子节点;对于最大堆来说,堆中每个父节点都要大于等于其子节点。

  • 设节点总数为 nnn,则堆的高度为 O(log⁡n)O(\log n)O(logn),插入操作、删除优先级最高的 entry 的操作的时间复杂度均为 O(log⁡n)O(\log n)O(logn)

  • 假设自顶向下对堆的每一层、从左到右对每个节点进行编号,且编号从 0 开始,则有:

    • 假设节点 xxx 的编号为 iii,且存在左右孩子,则 xxx 的左孩子的编号为 2i+12i+12i+1,右孩子的编号为 2i+22i+22i+2
    • 假设节点 xxx 的编号为 iii,且存在父节点,则其父节点的编号为 ⌊(i−1)/2⌋\lfloor (i-1)/2 \rfloor(i1)/2

以下以最小堆为例。

在这里插入图片描述

3. 插入

假设待插入的 entry 为 eee

(1)首先在堆尾之后的一个位置插入一个新节点,并存储 eee
(2)假设当前节点为 xxx(初始时,xxx 为尾后节点),其父节点为 ppp
(3)如果 p.entry≤x.entryp.entry \le x.entryp.entryx.entry,则成功返回;否则,
(4)上滤:如果 x.entry<p.entryx.entry \lt p.entryx.entry<p.entry,则令 x.entryx.entryx.entryp.entryp.entryp.entry 互换位置,然后令 xxx 指向 ppp,令 ppp 指向 ppp 的父节点,接着回到步骤(3)。

4. 删除

待删除的 entry 总是位于堆顶。

(1)首先,交换堆顶和堆尾的 entry,然后将堆的大小减一(堆尾前移),以删除堆顶元素(被删除的元素位于堆尾之后的一个位置);
(2)令当前节点为 ppp(初始时,ppp 为堆顶);
(3)令 xxxppp 的两个孩子节点中较小的一个;
(4)如果 p.entry≤x.entryp.entry \le x.entryp.entryx.entry,则成功返回;否则,
(5)下滤:如果 x.entry<p.entryx.entry \lt p.entryx.entry<p.entry,则令 x.entryx.entryx.entryp.entryp.entryp.entry 互换位置,然后令 ppp 指向 xxx,接着回到步骤(3)。

5. 建堆

如下图所示,假设 H0,H1H_0, H_1H0,H1 是两个最小堆,现欲将节点 ppp 和最小堆 H0,H1H_0,H_1H0,H1 合并为一个新的最小堆。

所需操作是:

(1)令 H0H_0H0ppp 的左孩子,H1H_1H1ppp 的右孩子;
(2)接着,从 ppp 开始执行下滤操作即可。

在这里插入图片描述
因此,给定一个数组,其大小为 nnn,现欲使用它构建一个最小堆所需的操作为:

(1)设当前节点为 xxx,其节点编号为 mmm,初始时,xxx 为堆的最后一个内部节点,编号为 m←⌊(n−2)/2⌋m \leftarrow \lfloor (n-2)/2 \rfloorm(n2)/2
(2)如果 m<0m \lt 0m<0,则返回;否则,从 xxx 开始执行下滤操作(先将子树 xxx 转换为一个最小堆);
(3)接着将 xxx 指向前一个内部节点,其编号为 m←m−1m \leftarrow m-1mm1,然后回到步骤(2)。

上述建堆操作的时间复杂度为 O(n)O(n)O(n)

6. 堆排序

总体而言,堆排序的过程为:对堆执行 nnn 次删除操作,因此其时间复杂度为 O(nlog⁡n)O(n\log n)O(nlogn)

因为每次删除操作都会将被删除的堆顶元素放到堆尾,而且堆的大小也在不断地减一(堆尾随之不断地向前移动),因此,最后的数组将包含排序后的元素。

对于最小堆来说,堆排序的直接结果是逆序的;而对于最大堆来说,则是顺序的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值