栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

深入理解heap

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深入理解heap

深入理解heap
  • binary heap
  • heap算法
    • push_heap算法
    • pop_heap算法

binary heap

binary heap是一种complete binary tree(完全二叉树),也就是说,整棵binary tree除了最底层的叶节点之外,是填满的,而最底层的叶节点由左到右又不得有空隙,如图所示:


complete binary tree整棵树内没有任何节点漏洞,这带来一个极大的好处:我们可以利用array来存储所有节点,假设动用一个小技巧,将array的#0元素保留,那么当complete binary tree中的某个节点位于array的i处时,其左节点必位于array的2i处,其右节点必位于array的2i+1处,其父节点必位于i/2处(此处的"/‘’权且代表高斯符号,取其整数),这种通过array表述tree的方式,我们称为隐式表述法
array的缺点是无法动态改变大小,以vector代替array是更好的选择
根据元素排列方式,heap可分为max—heap和min—heap两种,前者每个节点的键值都大于或等于其子节点键值,后者的每个节点键值都小于或等于其子节点键值

heap算法 push_heap算法

下图所示的是push_heap算法的实际操演情况,为了满足complete binary tree的条件,新加入的元素一定要放在最下一层作为叶节点,并填补在由左至右的第一个空格,也就是把新元素插入在底层vector的end()处

新元素是否适用于其现有位置?为满足max-heap的条件,我们执行一个所谓的percolate up(上溯)程序,将新节点拿来与其父节点比较,如果其键值比父节点大,就父子对换位置,如此一直上溯,直到不需对换或直到根结点为止
下面是算法的实现细节:

template
void _push_heap(RandomAccessIterator first,Distance holeIndex,Distance topIndex,T value)
{
	Distance parent=(holdIndex-1)/2;//找出父节点
	while(holeIndex>topIndex&&*(first+parent)
		//当尚未到达顶端,且父节点小于新值
		//由于以上使用operator<.可知STL heap是一种max-heap
		*(first+holeIndex)=*(first+parent);//令洞值为父值
		holeIndex=parent;//调整洞号,向上提升至父节点
		parent=(holeIndex-1)/2;//新洞的父节点
	}//持续至顶端,或满足heap的次序特性为止
	*(first+holdIndex)=value;//令洞值为新值,完成插入操作
}
pop_heap算法

如图所示:

下面是pop_heap算法的实现细节

template
void _adjust_heap(RandomAccessIterator first,Distance holeIndex,Distance len,T value)
{
	Distance topIndex=holeIndex;
	Distance secondChild=2*holeIndex+2;
	while(secondChild
		//比较洞节点之左右两个子值,然后以secondChild代表大子节点
		if(*(first+secondChild)<*(first+(secondChild-1)))
			secondChild--;
		//令较大子值为洞值,再令洞号下移至较大子节点处
		*(first+holeIndex)=*(first+secondChild);
		holeIndex=secondChild;
		//找出新洞节点的右子节点
		secondChild=2*(secondChild+1);
	}
	if(secondChild==len)//没有右节点,只有左节点
	{
		*(first+holeIndex)=*(first+(secondChild-1));
		holeIndex=secondChild-1;
	}
	//将欲调整值填入目前的洞号内,注意,此时肯定满足次序特性
	_push_heap(first,holeIndex,topIndex,value);
}

注意,pop_heap之后,最大元素只是被置放于底部容器的最尾端,尚未被取走,如果要取其值,可使用底部容器(vector)所提供的back()操作函数,如果要移除它,可使用底部容器所提供的pop_back()的操作函数

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1021136.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号