二叉树
定义:
在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(leftsubtree)和“右子树”(rightsubtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的i-1次方个结点;深度为k的二叉树至多有2^(k)-1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的结点数为n2,则n0=n2 + 1;
树和二叉树的2个主要差别:
-
树中结点的最大度数没有限制而二叉树结点的最大度数为2
-
树的结点无左、右之分,而二叉树的结点有左、右之分。
树的定义:
⒈必有一个特定的称为根(ROOT)的结点;
⒉剩下的结点被分成n>=0个互不相交的集合T1、T2、......Tn,而且,这些集合的每一个又都是树。树T1、T2、......Tn被称作根的子树(Subtree)。
树的递归定义如下:(1)至少有一个结点(称为根)(2)其它是互不相交的子树
1.树的度——也即是宽度,简单地说,就是结点的分支数。以组成该树各结点中最大的度作为该树的度,如上图的树,其度为3;树中度为零的结点称为叶结点或终端结点。树中度不为零的结点称为分枝结点或非终端结点。除根结点外的分枝结点统称为内部结点。
2.树的深度——组成该树各结点的最大层次,如上图,其深度为3;
3.森林——指若干棵互不相交的树的集合,如上图,去掉根结点A,其原来的二棵子树T1、T2、T3的集合{T1,T2,T3}就为森林;
4.有序树——指树中同层结点从左到右有次序排列,它们之间的次序不能互换,这样的树称为有序树,否则称为无序树。
}
}
树的表示:
树的表示方法有许多,常用的方法是用括号:先将根结点放入一对圆括号中,然后把它的子树由左至右的顺序放入括号中,而对子树也采用同样的方法处理;同层子树与它的根结点用圆括号括起来,同层子树之间用逗号隔开,最后用闭括号括起来。如上图可写成如下形式:(A(B(E(K,L),F),C(G),D(H(M),I,J)))
二叉树的基本形态:
二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:
(1)空二叉树——(a);
(2)只有一个根结点的二叉树——(b);
(3)只有左子树——(c);
(4)只有右子树——(d);
(5)完全二叉树——(e)
注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。
重要概念:
(1)完全二叉树——若设二叉树的高度为h,除第h层外,其它各层(1~h-1)的结点数都达到最大个数,第h层有叶子节点,并且叶子节点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶结点都处在最底层的二叉树。
(3)深度——二叉树的层数,就是高度。
性质:
(1)在二叉树中,第i层的结点总数不超过2^(i-1);
(2)深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;
(3)对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,
则N0=N2+1;
(4)具有n个结点的完全二叉树的深度为int(log2n)+1
(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
若I为结点编号则如果I<>1,则其父结点的编号为I/2;
如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
(6)给定N个节点,能构成h(N)种不同的二叉树。
h(N)为卡特兰数的第N项。h(n)=C(n,2*n)/(n+1)。
(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i
重点:
1二叉树的建立:
树的结构体定义:
struc tnode{
struct node *left , *right;
int v;//节点的值
};
node *root;//创建一个根节点
节点的初始化函数:
node* newnode(){
node*u = new node;
u-> v = 0;
u-> left = u -> right = NULL;
return u;
}
二叉树增加节点:
void addnode(){
node*u = new node;
if(u== NULL)
u-> newnode();// 建立新的节点
else
u → v = n;
}
二叉树的三种遍历:
/*******************************************/
/* 1按照前序递归遍历二叉树*/
/*******************************************/
voidPreorder1(node t)
{
if(t != NULL)
{
printf("%d",t->v);
Preorder1(t->lchild);
Preorder1(t->rchild);
}
}
/*******************************************/
/* 2按照中序递归遍历二叉树*/
/*******************************************/
voidInorder1(node t)
{
if(t != NULL)
{
Inorder1(t->lchild);
printf("%d",t->v);
Inorder1(t->rchild);
}
}
/*******************************************/
/* 3按照后序递归遍历二叉树*/
/*******************************************/
voidPosorder1(node t)
{
if(t != NULL)
{
Posorder1(t -> lchild);
Posorder1(t->rchild);
printf("%d",t->v);
}
}
<style type="text/css"> <!-- @page {margin:2cm} p {margin-bottom:0.21cm; direction:ltr; color:#000000; text-align:justify; widows:0; orphans:0} p.western {font-family:"Times New Roman",serif; font-size:10pt} p.cjk {font-family:"宋体","SimSun"; font-size:10pt} p.ctl {font-family:"Times New Roman",serif; font-size:12pt} a:link {} --> </style>
《二叉树的重建》
由中序和后序遍历序列进行建树,返回根结点指针
mid为中序的数组名,post为后续数组名,len为个数
Node* InPostCreateTree(int *mid , int *post , int len){
if(len== 0)
return NULL;
inti=len-1;
while(post[len-1]!= mid[i])
--i;
Node *h = NewNode();
h->data = post[len-1];
h->left = InPostCreateTree(mid,post,i);
h->right=InPostCreateTree(mid+i+1,post+i,len-i-1);
return h;
}
由前序和中序遍历序列进行建树,返回根结点的指针
//同上类似
Node* PreInCreateTree(int *mid , int *pre , int len) //n标识s2的长度
{
if(len==0)
return NULL;
inti = 0;
while(*mid!= pre[i])
++i;
Node *h = NewNode();
h->data=*mid;
h->left = PreInCreateTree(mid+1, pre, i);
h->right= PreInCreateTree(mid+i+1, pre+i+1, len-i-1);
returnh;
}