数据结构-堆

1.容器

容器用于容纳元素集合,并对元素集合进行管理和维护.

传统意义上的管理和维护就是:增,删,改,查.

我们分析每种类型容器时,主要分析其增,删,改,查动作实现,及复杂度.

2.堆

2.1.结构

2.1.1.图解

堆是容器类型.

采用容器内元素在线性空间连续存储的组织方式(数组也是如此).

但除此之外,基于元素的组织方式,为其抽象出了一层二叉树的逻辑关系.

以一个具体实例来说明.

上图是代表了一个可容纳12个元素的线性空间.现在存储了8个有效元素.堆的元素存储和数组一致.

但堆为其顺序存储的元素抽象出了一层二叉树的逻辑关系.

抽象的过程为,对顺序存储的每个元素,依次用这些元素顺序填满一颗满二叉树.

所谓满二叉树指的是,除了树最后一层,其余各层均是满的.最后一层,最后一个元素左边各个元素均是存在的.

如果观察特点可以得出以下结论,对顺序存储中索引为nIndex的元素.

逻辑结构里,其左孩子是索引为(2*nIndex+1)的元素,其右孩子是索引为(2*nIndex+2)的元素.

堆针对逻辑结构又施加了一层限制.

对最大堆来说,这层限制是:对堆中任一元素,该元素需要大于等于其左孩子,其右孩子上的元素.

对最小堆来说,这层限制是:对堆中任一元素,该元素需小于等于其左孩子,其右孩子上的元素.

在以上条件均满足下,可被利用的性质是:

(1). 首个元素是所有元素中最大的(对最大堆),最小的(对最小堆).

(2). 抽象出来的二叉树由于是满二叉树,其高度为:log2为底n的对数.

2.1.2.存在一致性约束容器特点

(1). 插入无需提供位置信息.

(2). 不支持直接原地修改.一般分解为移除,添加两个过程.

(3). 由于元素值决定其位置,这类容器一般插入元素时,以std::pair<key, value>形式插入.即元素包含键,值两部分.键用来实现一致性约束.值是此键关联的实际内容.

2.2.动作

2.2.0.建堆

意思是直接给一个连续存储的元素集合,把这些元素集合调整为符合堆性质的元素集合.

最直观当然是对集合内每个元素直接执行插入,这样所有元素插入完毕,就得到一个由这些元素构成的堆.

这里介绍另一种方式.

从集合最后一个元素反向遍历到第一个元素.

对每次遍历到的元素,让其符合:以该元素为根子树中所有元素均满足堆的性质.

下面介绍针对每个遍历到元素的调节过程.

不妨假设我们现在遍历到的元素是p.假设是最小堆.

由于我们之前每次遍历时,均按上述要求.所以,p的左孩子为根子树中所有元素此时均满足堆的性质.p的右孩子为根子树也是如此.此刻子树中唯一可能不满足要求的就是p和其左,右孩子.

p小于其左,右孩子上的元素,则无需调节.

否则,找到三者中最小元素q.交换此qp的位置.

交换后对p和其左右孩子来说堆的性质得到满足.但对q来说,由于此位置元素变大了.所以,此刻子树中只有q与其左右孩子可能不满足堆的性质.这样,我们虽然未立即解决问题.但将问题转化为了一个同类型问题.

由于树的高度有限,每次转化后我们在更低一层子树上再次处理同类问题.

故,即使最坏下,至多经过有限次调节,也可解决问题.

2.2.1.增

堆中插入新元素.对于存在一致性约束的容器,元素插入到容器后,需经历调节过程.不需要也无法在指定位置实现插入.具体位置依赖调节过程.

插入过程可描述为:

(1). 将新元素放在数组尾后位置.

(2). 这样,此时数组对应的二叉树中,只有新节点p和其父亲q可能不满足堆的性质.

(3). 我们分析最小堆场景.比较pq,若q中元素小于等于p,则无需调节.

(4). 若q中元素大于p,交换pq内元素.交换后,由于q位置元素变小了.所以,q和其父节点可能不满足堆的性质.p位置元素变小了.故,以p和其左右孩子必然满足堆的性质.

这样,我们虽然未立即解决问题,但将问题转化了.由于树的高度有限,故,最坏下也能经过有限次迭代结束调节过程.

2.2.2.删

堆由于其性质,一般移除限定只能移除首个元素.我们分析移除首个元素过程.

删除首元素可描述为:

(1). 交换尾元素和首元素.递减有效元素数量.

(2). 我们分析最小堆场景.此时,首元素p相比原来变大了.此时,整棵树中只有p和其左右孩子可能不满足堆的性质.

(3). 我们寻找节点p,其左孩子lp,其右孩子rp,三者中最小元素及其位置.

(4). 若最小元素是p,则无需调节.

(5). 若最小元素是某个孩子cp(要么lp,要么rp).交换cpp上元素.这样,交换后p和其左右孩子此时满足了堆的性质.但cp上元素变大了,所以,此时cp和其左右孩子可能不满足堆的性质.

这样,我们虽然未能立即解决问题.但将问题转化了.由于树的高度有限,故,最环下也能经过有限次迭代结束调节过程.

2.2.3.查

堆一般只提供访问首元素方法即可.

访问首元素直接基于索引访问即可.

2.2.4.改

对于存在一致性约束的容器,一般不会允许直接修改元素的值.

此类操作一般分解为:删除老元素,添加新元素两个过程来实现.

删除非首元素,类似删除首元素过程.只不过此时先交换删除位置元素和尾部元素.再从此开始进入调节流程.

2.3.时间复杂度

评价容器的依据一个是其占据的线性空间,一个是操作执行的时间复杂度.

堆的各个操作时间复杂度为:

(1). 增:Θ(log2为底n的对数)

(2). 删:Θ(log2为底n的对数)

(3). 查:Θ(1) (索引访问)

(4). 改:Θ(1) (log2为底n的对数)

相关推荐
wheeldown4 小时前
【数据结构】选择排序
数据结构·算法·排序算法
躺不平的理查德8 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
阿洵Rain8 小时前
【C++】哈希
数据结构·c++·算法·list·哈希算法
Leo.yuan8 小时前
39页PDF | 华为数据架构建设交流材料(限免下载)
数据结构·华为
半夜不咋不困8 小时前
单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构
数据结构·链表
忘梓.9 小时前
排序的秘密(1)——排序简介以及插入排序
数据结构·c++·算法·排序算法
y_m_h12 小时前
leetcode912.排序数组的题解
数据结构·算法
1 9 J12 小时前
数据结构 C/C++(实验三:队列)
c语言·数据结构·c++·算法
921正在学习编程12 小时前
数据结构之二叉树前序,中序,后序习题分析(递归图)
c语言·数据结构·算法·二叉树
毕竟秋山澪12 小时前
岛屿数量 广搜版BFS C#
数据结构·算法·宽度优先