优先队列--二叉堆
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]); } }
相关文章推荐
- 优先队列之二叉堆
- 数据结构之优先队列--二叉堆(Java实现)
- 优先队列(二叉堆实现) + 堆排序
- 图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)
- 优先队列和二叉堆
- 结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆
- 平行二叉堆和优先队列
- 图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)
- 二叉堆,堆排序,STL优先队列的底层实现,剑指offer数据流中的中位数
- 优先队列(二叉堆)的基本实现
- 排序算法(四):优先队列、二叉堆以及堆排序
- 优先队列 - 数据结构 (二叉堆)
- 排序算法之——优先队列经典实现(基于二叉堆)
- 优先队列--二叉堆实现
- 结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆
- 基于二叉堆实现的优先队列和堆排序
- [模板] 二叉堆 - 优先队列的二叉堆数组实现
- 数据结构之优先队列(二叉堆)
- 二叉堆实现优先队列中的上滤和下滤
- POJ3253 Fence Repair (二叉堆 | 优先队列 | huffman树 )