n叉树算法
① 哈夫曼树算法
题目的阐述:以N进制编码方式对一个英文字串中的字符进行编码,每个不同的字符其编码不同.使得由新的编码替代原串后总码长最小,且输入0,1,2,...,N-1构成的数字串后,依照该编码方式可以正确的对译出唯一的英文原串.如:N=3英文原串为ABBCBADDACE其对应的一种编码方式为A:00B:01C:020D:021E:022原串对译后的编码为000101020010002102100020022其码长为27若输入编码串0102002200则对应的英文原串为BCEA 分析: 假设英文原串中的字符存放于字符集S中,‖S‖=X,每个字符在字串中出现的概率为W[i],L[i]为字符i的编码长.依题意得,对S集合中的不同字符进行N进制编码后要求1)新字串的码长最短WPL=∑W[i]*L[i]
(i∈1..X)使得在WPL是所有编码方式中的最小值2)编码无二义性任意一字符编码都不为其它字符编码的前缀 此题以哈夫曼树来解答是非常适宜的.N为此哈夫曼树的分叉数,S字符集里的元素即为此N叉哈夫曼树的叶子,概率W[i]即为叶子结点的权重,从根结点到各叶子结点的路径长即为该叶子结点的编码长L[i].由哈夫曼树的思想可以知道哈夫曼树的建立是一步到位的贪心法,即权重越大的结点越靠近该树的根,这样,出现频率越大的字符其编码就越短.但具体应该怎样建立起此N叉哈夫曼树呢?我们首先以N=2为例:S={A,B,C,D}W=[3,1,2,1]首先从W中选出两个最小权,1,1,将其删去,并以2(即1+1)替代W=[3,2,2];再从新的W中取出两个最小权,2,2,将其删去,并以4(即2+2)替代W=[3,4];依此类推,直到W中只一个值时合并结束,此时W=[7]以上两两合并的过程即为二叉哈夫曼树的建立过程,每一次的合并即是将两棵子树归于一个根结点下,于是可以建立二叉树如下: m0åæ1mmA0åæ1mmC0åæ1mmBD MIN-WPL=3*1+1*3+2*2+1*3=13 从某一根结点出发走向其左子树标记为0,走向其右子树标记为1,则可以得到以下编码A,B,C,D对应的编码为A:0B:110C:10D:111
N=3时又是怎样一种情况呢?设S={A,B,C,D,E}W=[7,4,2,5,3}则按权重排序可得S={D,B,E,C,A}W=[7,5,4,3,2]那么此哈夫曼树的树形应为怎样呢?是以下的左图,还是右图,或是两者均不是mmåâæåæmmllmåæåæCAåælllllmADBEDåæ
lmBåællEC 显然,要带权路径长WPL最短,那么,此树的高度就应尽可能的小,由此可知将此树建成丰满N叉树是最合理的,于是我们尽量使树每一层都为N个分枝.对于这道题的情况,我们具体来分析.按照哈夫曼树的思想,首先从W中取出权最小的三个值,即2,3,4,并以9(2+3+4)来代替,得到新的W=[9,7,5];再将这三个值合并成9+7+5=21这个结点.于是得到三叉哈夫曼树如下:måâællmDBåâælllECAWPL=1*7+1*5+2*2+2*3+2*4=30以0..N-1依次标记每个根结点的N个分枝,则可以得到每个字符相对应的编码:A:22B:1C:21D:0E:20我们发现对于这种情况恰巧每层均为N个分枝,但事实上并非所有的N叉哈夫曼树都可得到每层N个分枝.例于当N=3,‖S‖=6时就不可能构成一棵每层都为三个分枝的三叉树.如何来处理这种情况呢?最简单的处理方式就是添加若干出现概率为0的空字符填补在N叉树的最下一层,这些权为0的虚结点并无实际意义但却非常方全便于这棵N叉树的建立.空字符的添加个数add的计算如下:Y=‖S‖mod(n-1)add=0(Y=1)add=1(Y=0)add=N-Y(Y>1) 虚结点的加入使得权重最小的N-add个字符构成了距根结点最远的分枝,使其它字符构成的N叉树保持了丰满的N叉结构.例:N=3S={A,B,C,D,E,F}W=[1,2,3,4,5,6}则y:=6mod(3-1)=0add=1于是构成N叉树如下:为虚结点¡åâællmFEåâællmDCåâæBAWPL=1*6+1*5+2*4+2*3+3*2+3*1+3*0=33对应编码为:A:221B:220C:21D:20E:1F:0
② 博弈树算法是啥
就是用树的节点来表示博弈过程中的每一步,比如在象棋里,双方棋手获得相同的棋盘信息。他们轮流走棋,目的就是将死对方,或者避免被将死。
由此,我们可以用一棵“博弈树”(一棵n叉树)来表示下棋的过程——树中每一个结点代表棋盘上的一个局面,对每一个局面(结点)根据不同的走法又产生不同的局面(生出新的结点),如此不断直到再无可选择的走法,即到达叶子结点(棋局结束)。
③ 二叉树各种计算公式总结有哪些
二叉树各种计算公式总结有n个节点的二叉树一共有2n除以n乘以 n+1这种,n层二叉树的第n层最多为2乘n减1个。二叉树节点计算公式 N 等于n0加n1加n2,度为0的叶子节点比度为2的节点数多一个。N等于1乘n1加2乘n2加1。具有n个节点的完全二叉树的深度为log2n加 1。
二叉树的含义
二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个最多只能有两棵子树,且有左右之分。
二叉树是n个有限元素的集合,该集合或者为空,或者由一个称为根的元素及两个不相交的,被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。
④ 完全n叉数的父节点怎么求pascal
n叉树的每层结点个数为
1
n^0
2
n^1
3
n^2
4
n^3
5
n^4
……
如果你会
等比数列
前n项的和就会算了
答案是(k+n-2)
div
n
不信自己可以带入几个数算算
给我加分吧
我还没被采纳过一次呢
……就算可怜可怜我
⑤ 求解具有n个结点的完全二叉树的深度,写出计算过程
具有n个结点的完全二叉树的深度为“log2n”+1
计算过程如下:
采用数学归纳法证明。
当n=1=2^1-1时,命题成立。
假设当n<=2^k-1时具有n个结点的完全二叉树的深度为“log2n”+1,
则当n=2^k(以及2^k+1,...,2^(k+1)-1)时,由归纳假设知:
前2^k-1个结点构成深度为“log2n”+1的树;
再由完全二叉树的定义知:
剩余的1(或2,...,2^k)个结点均填在第“log2n”+2层上(作为“叶子”),深度刚好增加了1,
故n<=2^(k+1)-1时,命题成立。
(5)n叉树算法扩展阅读:
二叉树是一种树型结构,它的特点是每个结点至多只有二棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。
二叉树的性质
1、在二叉树的第i层上至多有2i-1个结点;
2、深度为k的二叉树至多有2k-1个结点(k>=1);
3、对任何一棵二叉树T,如果其终端结点数为N0,度为2的结点数为N2,则N0=N2+1;
4、具有n个结点的完全二叉树的深度为“log2n”+1。
⑥ 二叉树基本算法
#include <iostream.h>
typedef struct BiTNode
{
char data;
int bit;
struct BiTNode *lchild,*rchild,*parent;
}BiTNode;
void InitBT(BiTNode *&t)//1、初始化,不带头结点
{
t=NULL;
}
/*void InitBT(BiTNode *t)//初始化,带头结点
{
t=new BiTNode;
t->lchild=t->rchild=t->parent=NULL;
}*/
int EmptyBT(BiTNode *t)//判断队空
{
if(t==0)
return 1;
else
return 0;
}
BiTNode *creatBT(BiTNode *t,int b)//2、创建二叉树
{
BiTNode *p;
char ch;
cin>>ch;
if(ch=='#')return 0;
else
{
p=new BiTNode;
p->data=ch;
p->parent=t;
p->bit=b;
t=p;
t->lchild=creatBT(t,0);
t->rchild=creatBT(t,1);
}
return t;
}
void preorder(BiTNode *t)//3、先序遍历
{
if(!EmptyBT(t))
{
cout<<t->data;
preorder(t->lchild);
preorder(t->rchild);
}
}
void inorder(BiTNode *t)//中序遍历
{
if(!EmptyBT(t))
{
inorder(t->lchild);
cout<<t->data;
inorder(t->rchild);
}
}
void postorder(BiTNode *t)//后序遍历
{
if(!EmptyBT(t))
{
postorder(t->lchild);
postorder(t->rchild);
cout<<t->data;
}
}
void coutBT(BiTNode *t,int &m,int &n,int &i)//4、计算二叉树中叶子结点、度为2的结点和度为1的结点的个数
{
if(!EmptyBT(t))
{
if((t->lchild==0) && (t->rchild==0))
m++;//叶子结点
else if((t->lchild!=0) && (t->rchild!=0))
i++;//度为2的结点
else
n++;//度为1的结点
coutBT(t->lchild,m,n,i);
coutBT(t->rchild,m,n,i);
}
}
void coutNode(BiTNode *t,int &k)//5、求二叉树中结点个数
{
if(!EmptyBT(t))
{
k++;
coutNode(t->lchild,k);
coutNode(t->rchild,k);
}
}
int BTdepth(BiTNode *t)//6、求二叉树的深度
{
int i,j;
if(EmptyBT(t))
return 0;
else
{
i=BTdepth(t->lchild);
j=BTdepth(t->rchild);
return (i>j?i:j)+1;
}
}
int Xdepth(BiTNode *t,char x)//7、查找x的层数
{
int num1,num2,n;
if(t==NULL)
return 0;
else{
if(t->data==x)
return 1;
num1=Xdepth(t->lchild,x);
num2=Xdepth(t->rchild,x);
n=num1+num2;
if(num1!=0||num2!=0)
n++;
return n;
}
}
static int flag;
void SearchChild(BiTNode *t,int k)//8、查找第k个结点的左右孩子
{
if(!EmptyBT(t))
{
if(k==0)
{
cout<<"位置不能为0!"<<endl;
return;
}
else
{
flag++;
if(flag==k)
{
if(t->lchild==0)
cout<<"无左孩子! ";
else
cout<<"左孩子为:"<<(t->lchild->data)<<" ";
if(t->rchild==0)
cout<<"无右孩子!"<<endl;
else
cout<<"右孩子为:"<<(t->rchild->data)<<endl;
}
else
{
SearchChild(t->lchild,k);
SearchChild(t->rchild,k);
}
}
}
}
int Xancestor(BiTNode *t,char x)//9、查找x结点祖先
{
int n,num1,num2;
if(t==NULL)
return 0;
else
{
if(t->data==x)
return 1;
num1=Xancestor(t->lchild,x);
num2=Xancestor(t->rchild,x);
n=num1+num2;
if(n!=0)
{
n++;
cout<<t->data<<" "<<endl;
}
}
}
void BTNodePath(BiTNode *t)//10、输出所有叶子结点路径
{
if(!EmptyBT(t))
{
if((t->lchild==0) && (t->rchild==0))
{
cout<<t->data<<"的路径为:";
for(BiTNode *p=t;p!=0;p=p->parent)
cout<<p->data;
cout<<endl;
}
else
{
BTNodePath(t->lchild);
BTNodePath(t->rchild);
}
}
}
void BTNodebit(BiTNode *t)//11、输出所有叶子结点编码
{
if(!EmptyBT(t))
{
if((t->lchild==0) && (t->rchild==0))
{
cout<<t->data<<"的编码为:";
for(BiTNode *p=t;p->parent!=0;p=p->parent)
cout<<p->bit;
cout<<endl;
}
else
{
BTNodebit(t->lchild);
BTNodebit(t->rchild);
}
}
}
void main()
{
BiTNode *t;
int m,n,i,d,q,k;
char x;
cout<<"1、初始化..."<<endl;
InitBT(t);
cout<<"2、创建二叉树..."<<endl;
t=creatBT(t,0);
cout<<"3.1、先序遍历..."<<endl;
preorder(t);
cout<<endl;
cout<<"3.2、中序遍历..."<<endl;
inorder(t);
cout<<endl;
cout<<"3.3、后序遍历..."<<endl;
postorder(t);
cout<<endl;
m=n=i=0;
cout<<"4、计算叶子结点,度为1的结点和度为2的结点的个数..."<<endl;
coutBT(t,m,n,i);
cout<<"叶子结点个数为:"<<m<<endl;
cout<<"度为1的结点个数为:"<<n<<endl;
cout<<"度为2的结点个数为:"<<i<<endl;
q=0;
cout<<"5、计算结点个数..."<<endl;
coutNode(t,q);
cout<<"结点个数为:"<<q<<endl;
d=0;
cout<<"6、计算深度..."<<endl;
d=BTdepth(t);
cout<<"深度为:"<<d<<endl;
cout<<"7、求x的层数..."<<endl;
cout<<"输入x:";
cin>>x;
if(Xdepth(t,x)==0)
cout<<"x不存在!"<<endl;
else
cout<<Xdepth(t,x)<<endl;
cout<<"8、输入要查找孩子的结点在先序遍历中的位置k(不等于0):";
cin>>k;
SearchChild(t,k);
if(k>flag)
cout<<"位置超出长度!"<<endl;
cout<<"9、查询结点的所有祖先,请输入结点x:";
cin>>x;
int num;
num=Xancestor(t,x);
if(num==0)
cout<<"结点不存在!"<<endl;
if(num==1)
cout<<"根结点无祖先!"<<endl;
cout<<"10、输出所有叶子结点路径(叶→根):"<<endl;
BTNodePath(t);
cout<<"11、输出所有叶子结点编码(叶→根):"<<endl;
BTNodebit(t);
}
⑦ 二叉树算法是什么
二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。
二叉树的第i层至多有2^(i 1)个结点;深度为k的二叉树至多有2^k 1个结点;对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0 = n2 + 1。二叉树算法常被用于实现二叉查找树和二叉堆。
二叉树是每个节点最多有两个子树的有序树。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
(7)n叉树算法扩展阅读:
二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树算法有五种基本形态:
1、空二叉树——(a)
2、只有一个根结点的二叉树——(b);
3、右子树为空的二叉树——(c);
4、左子树为空的二叉树——(d);
5、完全二叉树——(e)
注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。
⑧ 给出一个n叉树,一个叶子节点值,求这个叶子节点的路径,非递归
你的这个要求实在是太高了,是不可能有人满足你的要求的。因为:(1)、首先数据结构这门课程就是计算机软件专业中一门难度非常大的课程;(2)、而且了,关于将递归算法修改成等价的非递归算法,如果没有非常坚实的软件基础,那是绝对不可能将递归的程序修改成非递归程序的。
⑨ 二叉树的深度怎么算
二叉树的深度计算,首先要判断节点,以下是计算二叉树的详细步骤:
1、一颗树只有一个节点,它的深度是1;
2、二叉树的根节点只有左子树而没有右子树,那么可以判断,二叉树的深度应该是其左子树的深度加1;
3、二叉树的根节点只有右子树而没有左子树,那么可以判断,那么二叉树的深度应该是其右树的深度加1;
4、二叉树的根节点既有右子树又有左子树,那么可以判断,那么二叉树的深度应该是其左右子树的深度较大值加1。
一棵深度为k,且有2^k-1个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。
具有n个节点的完全二叉树的深度为floor(log2n)+1。深度为k的完全二叉树,至少有2k-1个叶子节点,至多有2k-1个节点。
5、有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
若I为结点编号则 如果I>1,则其父结点的编号为I/2;
如果2*I<=N,则其左孩子(即左子树的根结点)的编号为2*I;若2*I>N,则无左孩子;