双端堆
来源:互联网 发布:windows 压力测试 编辑:程序博客网 时间:2024/05/17 22:24
源地址:http://qxavier.me/2011/07/25/deap/
双端堆的特点
双端堆是一棵满二叉树,最顶端的根是一个虚根,不存放数据。定义element(N)为节点N的所有子孙节点(不包括N本身)的集合,N的左孩子left(N)(如果有的话)是element(N)中最小的元素,右孩子right(N)(如果有的话)是element(N)中最大的元素。
当以下条件成立时,它才是双端堆:
- P1:每个节点的元素小于等于它的右兄弟(如果有)
- P2:对于每个有祖父的节点N,其祖父节点的左孩子小于等于N
- P3:对于每个有祖父的节点N,其祖父节点的右孩子大于等于N
比如下图就是一个双端堆
下面我们看看实现
既然是一个满二叉树,那么就可以像堆一样有一个数组来表示,下标为n的节点的左右孩子的下标分别为2×n和2×n+1。
插入操作
现将该元素放在树的最后,看有没有满足性质P1,若违反,交换两节点的内容。再看是否满足上面讲的性质P2或者P3,如果满足,就将元素放在当前位置;若没有:
- 违反P2,将当前节点与其祖父的左孩子交换,祖父的左孩子变成当前节点;
- 违反P3,将当前节点与其祖父的右孩子交换,祖父的右孩子变成当前节点。
重复进行判断,直至找到合适的位置。
假设插入2,过程如下图:
=> =>
代码如下:
public void insert (T data) throws Exception{int curIdx = ++ size;if ( size >= HEAP_MAX_SIZE )throw new Exception();int grandpa;int parentMin, parentMax;//爷爷的左右孩子while (true){//是否有更大的左兄弟if ( (curIdx & 1) == 1 && data.compareTo(heap[curIdx-1]) < 0 ){heap[curIdx] = heap[curIdx-1];-- curIdx;}grandpa = curIdx >> 2;if ( grandpa == 0 )break;parentMin = grandpa << 1;parentMax = parentMin + 1;if ( heap[parentMin].compareTo(data) > 0 ){heap[curIdx] = heap[parentMin];curIdx = parentMin;}else if ( heap[parentMax].compareTo(data) < 0 ){heap[curIdx] = heap[parentMax];curIdx = parentMax;}elsebreak;}heap[curIdx] = data;}
删除操作
这里面的删除操作应该是指找到并删除最小(大)元素,找到很容易,最小元素是根的左孩子,最大元素是根的右孩子。但是,删除之后怎么调整以满足双端堆的特性呢?我们以删除最小元素为例,算法如下:
我们将树的最后一个元素暂时放在删除元素的位置,判断两个条件:
是否满足P1,不满足则交换两元素
与其左孩子、以及右兄弟节点的左孩子(如果有的话)比较,是否是最小的,不是则与最小的节点交换。(其左孩子和右兄弟的左孩子是两个次小的节点)
重复以上判断,直至满足这两个条件。
如果删除4的话,过程如下图:
=> => => =>
代码如下:
public T deleteMin () throws Exception{if ( size < 2 )throw new Exception();if ( size == 2 )return heap[size --];T tmp;int minChildIdx;T data = heap[size --];int curIdx = 2;T ret = heap[curIdx];while ( true ){if ( (curIdx & 1) == 0 && curIdx + 1 <= size && data.compareTo(heap[curIdx+1]) > 0 ){tmp = heap[curIdx+1];heap[curIdx+1] = data;data = tmp;}minChildIdx = curIdx << 1;if ( minChildIdx > size )break;if ( ((curIdx + 1) << 1) <= size && heap[minChildIdx].compareTo(heap[(curIdx+1)<<1]) > 0 )minChildIdx = (curIdx + 1) << 1;if ( data.compareTo(heap[minChildIdx]) > 0 ){heap[curIdx] = heap[minChildIdx];curIdx = minChildIdx;}elsebreak;}heap[curIdx] = data;return ret;}
- 双端堆
- 36 双端堆
- 优先队列-双端堆
- 双端堆/最小-最大堆/Double-Ended Heap ?
- 数据结构——双端堆(C语言)
- 最小最大堆(双端堆)的实现(Java版)
- VC中获取桌面工作区与任务栏大小
- win8开发(15)——扩展联系人选择器
- php session 详解
- Asp.net web Api源码分析-ParameterBindingAttribute
- eclipse载入extjs4出现内存溢出错误的解决方法
- 双端堆
- jmail
- win8开发(16)——如何处理溢出文本
- 重装系统后 防止病毒再侵袭的五大技巧
- I,P,B帧和PTS,DTS的关系
- 【Android】拷贝文件到另一个目录下
- STM32之 启动文件详细解析(V3.5.0)
- 路由器的密码和ios恢复
- win8开发(17)——自己也来做一做弹出对话框