堆、优先队列极其应用

简单介绍

堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值;
  • 堆总是一棵完全二叉树。

将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

堆是非线性数据结构,相当于一维数组,有两个直接后继。
堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
( k i ≤ k 2 i 且 k i ≤ k 2 i + 1 ) 或 ( k i ≤ k 2 i 且 k i ≤ k 2 i + 1 ) (k_i \leq k_{2i} 且 k_i \leq k_{2i + 1}) 或 (k_i \leq k_{2i} 且 k_i \leq k_{2i + 1}) kik2ikik2i+1kik2ikik2i+1
若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

以上摘自百度百科。

具体实现

下面给出小根堆的两种实现:

循环实现:

//省略头文件
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define fa(x) (x>>1)
class Heap
{
public:
	int a[(unsigned int)1e6 + 5], size;
	void insert(int num) {//num x size 分别是欲插入的数、位置、堆长度
		int x = ++size;
		while (a[fa(x)] > num && fa(x) >= 1) {//不断的和自己的父亲比较
			a[x] = a[fa(x)];//父亲赋值回孩子
			x = fa(x);//不要忘了更新 x 的值
		}
		a[x] = num;
		//show(size);
		return;
	}
	void pop() {//弹出最小的数
		if (size <= 0)return;//若堆以经没有值了就跳出函数
		size--;//堆长先减一
		int x = ls(1);
		while (x <= size) {
			if (x + 1 <= size && a[x + 1] < a[x])x++;//若右孩子在堆内且小于左孩子,则用右孩子
			if (a[x] < a[size + 1])a[fa(x)] = a[x], x = ls(x);
			else break;
		}
		a[fa(x)] = a[size + 1];//最后赋值
		return;
	}
	void show(int x) {
		printf("堆长 %d\n", size);
		int cnt = 0, p = 0;
		for (int i = 1, j = 0; i <= size; i +=j) {
			p++;
			for (j = 0; j < std::pow(2, p - 1) && i + j <= size; j++) {
				printf("%d ", a[++cnt]);
			}
			putchar('\n');
		}
		return;
	}
	Heap() { 
		memset(a, 0, sizeof a);
		size = 0;
	};
private:
}heap1;

//省略主函数

递归实现:

//(*╹▽╹*)头文件再见~~
#define fa(x) (x>>1)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
int heap[(unsigned int)1e7], hsize;
inline void heap_insert(int x, int num) {
	heap[x] = num;
	if (heap[fa(x)] > num && fa(x) >= 1) {
		heap[x] = heap[fa(x)];
		heap_insert(fa(x), num);
	}
	return;
}
inline void h_pop(int x, int num) {
	heap[x] = num;
	if (ls(x) <= hsize && num > heap[ls(x)] && heap[ls(x)] <= heap[rs(x)]) {
		heap[x] = heap[ls(x)];
		h_pop(ls(x), num);
	}
	else if (rs(x) <= hsize && num > heap[rs(x)] && heap[ls(x)] >= heap[rs(x)]) {
		heap[x] = heap[rs(x)];
		h_pop(rs(x), num);
	}
	return;
}
//省略主函数

小根堆的两种实现就是这样啦~
大根堆把里面的符号换一下就可以了,拜拜~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值