您的位置:首页 > 其它

优先队列--二叉堆

2012-11-12 19:21 211 查看

优先队列:

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

二叉堆:

二叉堆是一个完全二叉树,父节点大于子节点的叫做大顶堆,父节点小于子节点的叫做小顶堆,由于是一个完全二叉树,树的结构相对固定,所以可以用一个数组来存储。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]);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: