数据结构-堆

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的对数)

相关推荐
danaaaa1 小时前
算法力扣刷题 三十一【150. 逆波兰表达式求值】
数据结构·c++·算法·leetcode·职场和发展
know what one is about3 小时前
二分查找及其变种
数据结构·算法
我不会起名字呀5 小时前
leetcode216.组合总和III、40.组合总和II、39.组合总和
数据结构·算法
ziyue75759 小时前
将List切割为多个指定长度的多个List
java·数据结构·windows·list
joker D88811 小时前
红黑树插入删除流程(流程图)
数据结构·算法·流程图·红黑树
☆致夏☆11 小时前
Java-数据结构
数据结构
攻城狮7号13 小时前
【第五节】C/C++数据结构之图
c语言·数据结构·c++
激昂~逐流15 小时前
Leetcode秋招冲刺--(专题7-9)
数据结构·算法·leetcode
再玉米地里吃过亏16 小时前
LeetCode 子集
数据结构·c++·算法·leetcode·dfs
一个闪现必杀技16 小时前
数据结构速成--图
数据结构