学二叉堆有感

在认识二叉堆之前,先讲一下完全二叉树的定义:完全二叉树指的是除了最后一层的叶子节点意外,其他层的节点都有2个儿子,而且最后一层的叶子从左往右排,例如下图1是一棵完全二叉树,图2就不是。


二叉堆有2种:每个节点的值都小于等于其儿子节点的值的堆,称为最小堆;每个节点的值都大于等于其儿子节点的值的堆,称为最大堆。

以下以最小堆为例


设二叉堆的某个节点为p,它的左儿子是2p,右儿子是2p + 1,基于这个性质, 我们可以在O(1)的时间访问到每一个节点,而且我们可以直接把所有节点存在一维数组里,不需要链表和其他的数据结构。

图3是一个最小堆


二叉堆的基本操作:

 1. 插入节点,假设现在一共有n个节点,我们先把新的节点放在n+1的位置上,然后进行向上调整,调整的具体过程是这样的,每一次都拿当前节点的值和它父亲的值比较,如果当前节点的值已经大于等于它父亲的值,那么调整结束;如果当前节点的值小于它父亲的值,那么交换它们的值,然后继续往上调整

这个过程称为上滤

void heap_up(int p) //插入元素
{
	int fa_p = (p >> 1);
	while (fa_p >= 1)
	{
		if (heap[fa_p] <= heap[p])
		{
			break;
		}
		heap[p] ^= heap[fa_p];
		heap[fa_p] ^= heap[p];
		heap[p] ^= heap[fa_p];
		p = fa_p;
		fa_p >>= 1;
	}
} 

2.删除根节点,可以把根节点的值设为无穷大,然后向下调整,每一次拿节点p和它两个儿子里值小的那个进行比较,如p的值大于等于它的那个儿子,就进行交换,否则调整结束,我们可以准确定位到值为无穷大的节点的位置x, 然后将当前二叉堆最后一个节点的值赋给节点x,然后n--,就实现了删除根节点的功能

这个过程称为下滤

void heap_down()// 下滤
{
	son_p = (p << 1);
	while (son_p <= n)
	{
		if (son_p < n && heap[son_p] > heap[son_p | 1])
		{
			son_p |= 1;
		}
		if (heap[p] <= heap[son_p])
		{
			break;
		}
		heap[p] ^= heap[son_p];
		heap[son_p] ^= heap[p];
		heap[p] ^= heap[son_p];
		p = son_p;
		son_p <<= 1;
	}                      
}

有n个节点的二叉堆,它的层数是logn,所以插入和删除操作最坏的时间复杂度是O(logn)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值