数据结构-【堆】学习笔记

本文介绍了堆的基本概念,包括其性质和不同类型,如二叉堆(小根堆和插入删除算法)、左偏堆等。重点讲解了二叉堆的插入和删除操作,以及快速建堆的不同方法。通过实例演示,深入浅出地展示了堆在实际中的高效查询和维护能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆是一棵树。

这棵树的性质:一个节点的键值大于等于或小于等于其儿子的键值。

因为这个性质,可以在O(1)O(1)O(1)的时间查询最小值或最大值。

堆有很多种类型:二叉堆、配对堆、左偏树、斐波那契堆。

根据功能,还可以再分类:普通堆、可并堆、可持久化堆……

数据结构的树林十分繁密。

1、二叉堆

这是最基础,也是最常见最普遍应用最广的一种堆。

顾名思义,这是一棵二叉树。父亲的键值大于等于或小于等于左右儿子的键值。

iii的左右儿子分别是2i,2i+12i,2i+12i,2i+1

以小根堆为例:

  • 如何插入一个数?

一种比较简单的方式就是把数值放在最底层、最右边的结点xxx

x.val<fax.valx.val<fa_x.valx.val<fax.val,交换xxxfaxfa_xfax。重复此操作。

因为这是一棵完全二叉树,时间复杂度是O(lg⁡n)O(\lg_n)O(lgn)

  • 如何删除堆顶元素?

一种办法是把堆顶的值设到∞\infty,然后不断向下调整,最后删除。

还有一种办法是交换堆顶和最底层、最右边的结点,然后删掉最底层且最右边的元素(原堆顶)。

然后对新堆顶进行向下调整。

两种时间复杂度都是O(lg⁡n)O(\lg_n)O(lgn)

  • 能不能快速地建堆?

一种方法是从结点1开始不断加入结点(向上调整)。

for(int i=1;i<=n;i++) up(i);

时间复杂度是lg⁡1+lg⁡2+lg⁡3+...+lg⁡n=Θ(nlg⁡n)\lg_1+\lg_2+\lg_3+...+\lg_n=\Theta(n\lg_n)lg1+lg2+lg3+...+lgn=Θ(nlgn)

换一个思考方向:从结点nnn开始不断向下调整。

for(int i=n;i>=1;i--) down(i);

可以证明,时间复杂度是O(n)O(n)O(n)

证明一:自己想的。

最底层节点都只用进行一次操作,有n2\frac{n}{2}2n个结点。

倒数第二层最坏情况是两次操作,有n4\frac{n}{4}4n个结点。

……

第一层最坏情况是lg⁡n\lg_nlgn次操作,有nn=1\frac{n}{n}=1nn=1个结点。

于是记时间复杂度为SSS
                      S=n2×1+n4×2+n8×3+...+nn×lg⁡n①①×2→2S=n×1+n2×2+n4×3+...+2×lg⁡n②②−①→S=n+n2+n4+...+2+lg⁡n                                     =n(1+12+14+18+...+112n)+lg⁡n=O(n)                                      \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ S=\frac{n}{2}\times1+\frac{n}{4}\times2+\frac{n}{8}\times3+...+\frac{n}{n}\times \lg_n①\\ ①\times2\to2S=n\times1+\frac{n}{2}\times2+\frac{n}{4}\times3+...+2\times\lg_n②\\ ②-①\to S=n+\frac{n}{2}+\frac{n}{4}+...+2+\lg_n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =n(1+\frac{1}{2}+\frac{1}{4}+\frac{1}{8}+...+\frac{1}{\frac{1}{2}n})+\lg_n\\ =O(n)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \                       S=2n×1+4n×2+8n×3+...+nn×lgn×22S=n×1+2n×2+4n×3+...+2×lgnS=n+2n+4n+...+2+lgn                                     =n(1+21+41+81+...+21n1)+lgn=O(n)                                     
证明二:网上搬的。

具有nnn个结点的完全二叉树,树高h=lg⁡nh=\lg_nh=lgn,可知n=2hn=2^hn=2h

层数从0开始。

最底层(h−1h-1h1层)有2h−12^{h-1}2h1个结点,每个结点进行一次比较,效率是2h−1×12^{h-1}\times 12h1×1

倒数第二层有2h−22^{h-2}2h2个结点,每个结点进行两次比较,效率是2h−2×22^{h-2}\times 22h2×2

由此,可以写出第xxx层的效率=2x×(h−x)=2^{x}\times (h-x)=2x×(hx)

那么时间复杂度SSS
                         S=2h−1×1+2h−2×2+2h−3×3+...+20×h①①×2→   2S=2h×1+2h−1×2+2h−2×3+...+21×h②①−②→   S=2h×1+2h−1+2h−2+...+21+20×h        =2h+1−1+h                             =O(2n−1+lg⁡n)                       =O(n)                                           \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ S=2^{h-1}\times1+2^{h-2}\times2+2^{h-3}\times3+...+2^0\times h①\\ ①\times2\to\ \ \ 2S=2^h\times1+2^{h-1}\times2+2^{h-2}\times3+...+2^{1}\times h②\\ ①-②\to\ \ \ S=2^h\times1+2^{h-1}+2^{h-2}+...+2^1+2^0\times h\ \ \ \ \ \ \ \ \\ =2^{h+1}-1+h\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ =O(2n-1+\lg_n)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ =O(n)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \                          S=2h1×1+2h2×2+2h3×3+...+20×h×2   2S=2h×1+2h1×2+2h2×3+...+21×h   S=2h×1+2h1+2h2+...+21+20×h        =2h+11+h                             =O(2n1+lgn)                       =O(n)                                          
两者的方法类似,思考过程有差异。

左偏堆

留坑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值