二项树及二项队列
来源:互联网 发布:手机上淘宝网怎么付款 编辑:程序博客网 时间:2024/05/21 08:56
二项树及二项队列
二项队列是由二项树按照一定规则组成的森林,故先介绍二项树:
1 二项树
二项树是这样的一种树:设高度为k的树Bk有
单节点树 when k=0
高度为k的树是由上一棵高度k-1的树作为孩子附接到另一棵高度k-1的树而构成 when k~=0
例如:
分析二项树特点可知,当高度k=0时树中节点数为1
当k~=0时,设此时节点数目N(k)=2*N(k-1)=2^2N(k-2)=...=2^k*N(0)=2^k
且第d层的节点树满足二项式系数Cd/k,故命名这种树为二项树。
2 二项队列(森林)
将上述二项树多棵组成森林按照以下原则:
a.符合堆序(根值最大或最小)
b.每一高度k上最多只能有一棵树,例如有高度k=2二项树多棵时需要合并。
可以知道二项队列有如下特点:
a.它是由二项树构成的森林;
b.每种高度最多只有一棵二项树,故最多含有Log(N)棵树;
c.二项队列中每棵树按照树高度可记为B0 B1 B2。。。;
d.任意正整数可由二项队列表示如上图中表示的7=二进制111(B2B1B0)。
3 二项队列操作
搜索最小元:
可以通过搜索所有树的根来找出。由于最多有有log(N)棵树故搜索最小元耗时O(log N)
合并二项队列:
合并的核心操作是:
a 两个队列若只存在一个高度k的二项树,保留
b 两个队列若存在两个高度k相同的二项树H1中的t1和H2中的t2,要让大的根成为小的根的子树从而产生高度为k+1的类进位树记为carry
c 两个队列若只存在三个高度k的二项树,选择一个保留,剩下两个相合并
设H1 H2是两个二项队列,H3是合并之后二项队列,基本操作如下(0为不存在,1为存在):
carry t2 t1表示含义0 0 0该高度没有树0 0 1该高度只有t1树0 1 0该高度只有t2树1 0 0该高度只有carry树0 1 1该高度t2和carry树1 0 1该高度t1和carry树1 1 0该高度t1,t2树1 1 1该高度t1,t2和carry树合并两棵树只需常数时间,而最多log N棵树,故最多花费时间O(log N)
另外插入操作也可以归为合并,只不过是单节点的合并。以空队列插入1-7为例:
删除最小元:
主要操作:
a 找出一棵具有最小根的二项树并记为Bk,该二项队列为H
b 从H中的Bk删去根,剩下的为若干棵二项树B0,B1,B2。。。,Bk-1共同组成二项队列H11
c 从H中删去Bk,剩下的构成二项队列H22
d 合并H11 H22
合并:
查找最小和创建队列耗时O(log N),最终合并也是耗时O(log N)故最终耗时O(log N)。
4 二项队列C++实现
右上面分析可知,删除最小值需要快速找出根的所有子树,故每一个二项树表示方法采用左孩子右兄弟方法,且由一个指针数组存储每棵二项树的根节点
注意:
指针数组的大小一般至少是二项队列中二项树数目×2+1;
数组第 i 号索引处,存储的是高度为 i 的二项树。如,第0号索引,存储高度为0的二项树,该二项树只有一个结点,结点权值为13;
每棵二项树由左孩子右兄弟的链表保存;
诸孩子按照它们子树的大小排序。
.h 文件
#ifndef _binary_tree_#define _binary_tree_class binary_tree;class bin_node{ private:int key;bin_node*leftchild;bin_node*brother; public:bin_node():key(-10000),leftchild(NULL),brother(NULL){}friend binary_tree;};class binary_tree{ private:int size;bin_node *Tree[M]; public:binary_tree(){int i;for(i=0;i<M;i++)Tree[i]=new bin_node();size=0;}~binary_tree(){int i;for(i=0;i<M;i++)delete Tree[i];}//not delete []bin_node*combinetree(bin_node*t1,bin_node*t2);binary_tree mergequeue(binary_tree h1,binary_tree h2);int deletemin(binary_tree h);};#endif
需要注意的是析构函数对指针数组的处理。指针数组中每一个都是一个数组指针,每一个都是delete[] 数组名,故加一个for循环,而不能简单的delete[]指针数组名。
.cpp文件
//**************************binary_tree**********************//bin_node*binary_tree::combinetree(bin_node*t1,bin_node*t2){if(t1->key>t2->key) return combinetree(t2,t1);t2->brother=t1->leftchild;t1->leftchild=t2;return t1;}//相同高度binary_tree binary_tree::mergequeue(binary_tree h1,binary_tree h2){int i,j;bin_node*carry=NULL;//上一步得来的树类似加法里的进位bin_node*t1=NULL,*t2=NULL;h1.size+=h2.size;for(i=0,j=1;j<h1.size;i++,j*=2) {t1=h1.Tree[i];t2=h2.Tree[i]; switch(4*!!carry+2*!!t2+!!t1)// c t2 t1 // 0 0 0 {case 0:break;//no any trees case 1:break;//only t1 case 2:h1.Tree[i]=t2;h2.Tree[i]=NULL;break;//only t2 case 4:h1.Tree[i]=carry;carry=NULL;break;//only carry case 3:carry=combinetree(t1,t2); h1.Tree[i]=h2.Tree[i]=NULL;break;//t1,t2,carry case 5:carry=combinetree(t1,carry); h1.Tree[i]=NULL;break;//t1 carry case 6:carry=combinetree(t2,carry); h2.Tree[i]=NULL;break;//t2 carry case 7:h1.Tree[i]=carry; carry=combinetree(t1,t2);h2.Tree[i]=NULL;break;// t1 t2 carry } }//一共log2(size)棵时故执行log2(size)次return h1;}int binary_tree::deletemin(binary_tree h){int i,j;int min_index=0,min_value=h.Tree[min_index]->key;//先找到最小值所在的二项树for(i=0,j=1;j<h.size;i++,j*=2) { if(h.Tree[i]&&h.Tree[i]->key<min_value) {min_index=i;min_value=h.Tree[i]->key;} }bin_node*root=h.Tree[min_index];//删除最小值并重新构成优先队列H22bin_node*delete_tree=root->leftchild;free(root);binary_tree delete_queue;delete_queue.size=(1<<min_index)-1;//原始大小为2^(min_index) for(j=min_index-1;j>=0;j--) {delete_queue.Tree[j]=delete_tree; delete_tree=delete_tree->brother; delete_queue.Tree[j]->brother=NULL; }//去掉含最小值的二项树构成H11h.Tree[min_index]=NULL;h.size-=delete_queue.size+1;mergequeue(h,delete_queue);return min_value;}
- 二项树及二项队列
- 二项队列分析及实现
- 二项队列(类结构及节点定义)
- 二项队列
- 二项队列
- 二项队列
- 二项队列
- 二项队列
- 循环队列及C语言实现<二>
- 转载:优先队列:BinomialQueue 二项队列
- 优先队列基础知识(四)---二项队列
- 优先队列之二项队列
- 二项队列 (优先队列)~
- 二项队列添加元素
- 二项队列 C++实现
- 二项队列 C语言
- JAVA实现二项队列
- 第十五章(二) FIFO、消息队列及信号量
- 回归决策树
- 一,Spring容器BeanFactory和ApplicationContext对比
- 而立之年,未开始的创业路(暨 2016年总结)
- 如何让Machine Driver在Rancher中无比简单易用
- 数据结构——图—最小生成树(普里姆算法和克鲁斯卡尔算法)
- 二项树及二项队列
- [Java基础]接口能否被实例化以及匿名内部类
- 运行时加载DLL
- [51nod 1223]分数等式的数量
- 【C#】52. 使用Flatten方法处理并行任务抛出的异常
- vue2.0(新手)第一个坑--do not mount Vue to <body>!!!
- matlab-基于IBM服务器”VideoReader没有注册类“解决全过程
- Python install ggplot in Rodeo
- 导入第三方框架ReactiveCocoa经常出现的问题 如出现Could not build module ‘ReactiveCocoa’