NO.50十六届蓝桥杯备战|堆和priority_queue|向上调整|向下调整|堆的创建插入删除获取堆顶获取大小|sizeempty|push|pop|top|内置类型结构体类型(C++)

堆的定义

堆(heap),是⼀棵有着特殊性质的完全⼆叉树,可以⽤来实现优先级队列(priority queue)。
堆需要满⾜以下性质:

  1. 是⼀棵完全⼆叉树;
  2. 对于树中每个结点,如果存在⼦树,那么该结点的权值⼤于等于(或⼩于等于)⼦树中所有结点的权值。
    如果根结点⼤于等于⼦树结点的权值,称为⼤根堆;反之,称为⼩根堆

堆的存储

由于堆是⼀个完全⼆叉树,因此可以⽤⼀个数组来存储。
结点下标为i :

  • 如果⽗存在,⽗下标为i/2 ;
  • 如果左孩⼦存在,左孩⼦下标为i × 2 ;
  • 如果右孩⼦存在,右孩⼦下标为i × 2 + 1
    ![[Pasted image 20250319201731.png]]

![[Pasted image 20250319201529.png]]

存储固然简单,但是题⽬不会那么好⼼,直接给出⼀个标准的堆
⼀般给我们的是⼀组数,这组数按照给出的顺序还原成⼆叉树之后,并不是⼀个堆结构。此时如果想将这组数变成堆的话,有两种操作:

  1. ⽤数组存下来这组数,然后把数组调整成⼀个堆;
  2. 创建⼀个堆,然后将这组数依次插⼊到堆中

核⼼操作

堆中的所有运算,⽐如建堆,向堆中插⼊元素以及删除元素等,都是基于堆中的两个核⼼操作实现的—向上调整算法以及向下调整算法。
因此,在实现堆之前,先来掌握两种核⼼操作。
注意:以下所有操作都默认堆是⼀个⼤根堆,⼩根堆的原理反着来即可

向上调整算法

算法流程:

  1. 与⽗结点的权值作⽐较,如果⽐它⼤,就与⽗亲交换;
  2. 交换完之后,重复1 操作,直到⽐⽗亲⼩,或者换到根节点的位置
int n; // 标记堆的⼤⼩  
int heap[N]; // 存堆 - 默认是⼀⼤根堆  
// 向上调整算法  
void up(int child)  
{  
	int parent = child / 2;  
	// 如果⽗结点存在,并且权值⽐⽗结点⼤  
	while(parent >= 1 && heap[child] > heap[parent])  
	{  
		swap(heap[child], heap[parent]);  
		// 交换之后,修改下次调整的⽗⼦关系,注意顺序不能颠倒  
		child = parent;  
		parent = child / 2;  
	}  
}

时间复杂度:
最差情况需要⾛⼀个树⾼,因此时间复杂度为log N

向下调整算法

算法流程:

  1. 找出左右⼉⼦中权值最⼤的那个,如果⽐它⼩,就与其交换;
  2. 交换完之后,重复1 操作,直到⽐⼉⼦结点的权值都⼤,或者换到叶节点的位置
int n; // 标记堆的⼤⼩  
int heap[N]; // 存堆 - 默认是⼀⼤根堆  
// 向下调整算法  
void down(int parent)  
{  
	int child = parent * 2;  
	while(child <= n) // 如果还有孩
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值