数据结构--堆(优先队列)

本文介绍了堆的概念,特别是小顶堆,并详细阐述了如何手写堆,包括down和up函数的使用,以及插入、求最小值、删除最小值、删除任意元素和替换任意元素等操作。此外,还探讨了C++中的优先队列及其转换为小根堆的方法。

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

堆,实际上是一个完全二叉树,大概就是介个样子。。。
在这里插入图片描述
堆一般又分为大顶堆和小顶堆(实际上差不多。。。这里就用小顶堆举个例好了QwQ)

手写堆

其实STL中的优先队列已经有堆的作用了,但是手写的堆也有一些自己的优势。我们先来看看堆的一些常用操作。
1.插入一个数
2.求集合当中的最小值
3.删除最小值
4.删除任意一个元素
5.更改任意一个元素

前三个功能,都可以通过优先队列直接实现,而后面两个功能,用手写的堆更容易实现,所以。。。手写的堆,也是有优势滴QwQ
手写的堆可以用一维数组存储,虽然看起来5个功能很麻烦,但其实依赖两个函数就可以全部实现。
利用down(下沉)函数和up(上升)函数,两个函数就可以实现上面的功能。

down函数

down函数主要是为了把大的数往树的下方沉,每次比较选择子节点中较小的一个数,进行替换,模板如下

void down(int u)
{
	int t = u;     // t 用于找一个最小的节点值
	if(u * 2 <= size && h[t] > h[u * 2]) t = u * 2;     // h 用于存放堆
	if(u * 2 + 1 <= size && h[t] > h[u * 2 + 1]) t = u * 2 + 1;
	if(u != t)
	{
		swap(h[t], h[u]);
		down(t);     //利用递归的思想继续下沉
	}
}
up函数

同样的,up函数是为了让小的数往上升,模板也更简单,以为up函数只用和根节点比较就好了

void up(int u)
{
	while(u / 2 && h[u / 2] > h[u])
	{
		swap(h[u / 2], h[u]);
		u /= 2;
	}
}

几个操作的具体方法

1.插入

在数列尾部插入后上升

	scanf("%d", &x);
	h[++ size] = x;
	up(size);
2.求最小值

也就是在 1 位置的元素

	printf("%d", h[1]);
3.删除最小值

先把堆尾的元素赋值给堆首,再删除堆尾

	h[1] = h[size];
	size --;
	down(1);
4.删除任意元素

与删除最小值差不多,但是要注意你不知到替换之后数的大小情况,所以要down一遍,再up一遍

	scanf("%d", &k)
	h[k] = h[size];
	szie --;
	up(k), down(k);
5.替换任意元素

直接赋值以后,利用两个函数,找到替换后的位子就可以了

	scanf("%d%d", &k, &x);
	h[k] = x;
	up(k), down(k);

优先队列

优先队列,priority_queue也与堆有着相同的作用
priority_queue默认的情况是大根堆,我们有两种方法来把它变成小根堆,一种是直接输入负值,一种是在定义时就定义成小根堆,定义的方法还有一些常见的操作方法,都会在下面的代码中

	priority_queue<int, vector<int>, greater<int>> q;
	q.push()    // 插入一个元素
	q.pop()    //删除一个元素
	q.top()   //返回堆顶的元素

优先队列属于c++中的STL,是一个语法问题,在这也不多阐述了。
这就是堆的用法,是不是好简单的。。。(其实完全不知道有什么用。。。要不是最短路用的到才不会来学QwQ)
不管了,至少也算是学会了一个新知识点。。。怎么用以后再说吧QwQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值