优先队列--二叉堆

优先队列:

队列中的元素包含有优先级,可以实现优先级最高的先出列。


二叉堆:

二叉堆是一个完全二叉树,父节点大于子节点的叫做大顶堆,父节点小于子节点的叫做小顶堆,由于是一个完全二叉树,树的结构相对固定,所以可以用一个数组来存储。array[i]表示父节点的话,那他的左子节点为array[2*i],右子节点为array[2*i+1]。


操作:

insert(Comparable a);

deleteMin();

为了保证二叉堆的堆序性质,每次插入或者删除后都得对二叉堆进行调整,而删除插入的平均复杂度为树的高度O(logN)。


维护二叉堆的核心:


下滤是删除时需要的操作。deleteMin后二叉堆的根节点被删除,由于堆少了一个元素所以原来的最后一个元素X必须在他之前找到一个合适的位置安放,而根节点处产生了一个空穴,由于X不可能直接放入空穴,所以在根节点的子节点中选一个放入空穴(小顶堆的话选小的子节点,大顶堆选大的),进而把空穴推进至下一层重复该步骤直至,X能够放入该空穴为止。这个空穴从上往下推进的过程就叫做下滤.

	void percolatedown(int pos,Comparable value)
	{
		int hole=pos;
		int child;
		for(;hole*2<m_varray.size();)
		{
			child=hole*2;
			if(child+1<m_varray.size()&&m_varray[child]>m_varray[child+1])
				child++;
			if(value>m_varray[child])
				m_varray[hole]=m_varray[child];//将子节点中较小的放入至空穴
			else
				break;	//找到了合适的位置
			hole=child;//将空穴下移至下一层

		}
		m_varray[hole]=value;
	}
通过下滤来实现deleteMin

	Comparable deleteMin()
	{
		
		Comparable ret=m_varray[1];
		m_varray[1]=m_varray[m_varray.size()-1];
		m_varray.pop_back();
		if(m_varray.size()<2)
			return ret;
		percolatedown(1,m_varray[1]);
		return ret;
	
	}





上滤是对二叉堆插入数据时需要的操作,思路和下滤差不多,不过这次是因为多了一个元素,所以堆数组尾部多了一个位置即空穴,而要插入的元素X一般不可能能直接放入空穴,所以把空穴的父节点放入,这样空穴就往上推进了一层,重复该步骤直至X能够放入空穴位置。

在二叉堆中插入元素就用了上滤的策略,代码如下:

	void insert(Comparable value)
	{
		m_varray.push_back(value);
		int hole=m_varray.size()-1; //空穴开始在尾部
		while(hole>0)
		{
			if(m_varray[hole/2]>value)
			{
				m_varray[hole]=m_varray[hole/2]; //空穴上移一层
				hole/=2;
			}
			else
				break; //找到了合适的插入位置

		}
		m_varray[hole]=value;	
	
	}


上滤和下滤都是为了保证二叉堆的堆序性质。


构建一个二叉堆

1.通过原始集合构建:

对于一个有n个元素的集合可以通过n次插入实现二叉堆的构建,每个插入操作的最好情形为O(1),最坏情形为O(logN).

2.由无序二叉堆构建一个有序二叉堆:

1.想一下这种情况一个完全二叉树根节点root,左子树treeA,右子树treeB。左右子树都符合二叉堆的定义,怎样调整使其整体符合二叉堆的性质。这里和deleteMin中的情况相似,把这个根节点看成一个空穴,而里面的数据需要放到合适的位置,所以在这里进行下滤的操作:对根节点位置用根节点的数据进行下滤,完成后便成了二叉堆。

2.一棵二叉堆的树总是由左子树和右子树构成,所以我们要保证左子树和右子树都是二叉堆,然后对根节点进行下滤。对子树采取同样的操作。可以看成一个递归的过程。实际编码中可以用循环来代替这个递归。

比如下面这个无序二叉堆




我们可以从下往上从左往右来遍历,先调整110这个树为二叉堆,然后调整70,10,30,这样就保证第三层的子树都为二叉堆了,即第二层节点的子树全是二叉堆,然后再调整40,80这两颗子树...

具体构建代码:

	void BuildHeap()
	{
		for(int hole=(m_size/2);hole>0;hole--)
		{
			percolatedown(hole,m_array[hole]);
			
		}
	}











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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值