第六章 树
1.树是n个结点的有限集。n=0时称为空树。在任意一个非空树中:
(1)有且仅有一个特定的称为根的结点
(2)当n>1时,其余节点可分为m个互不相交的有限集,其中每一个集合又是一棵树,并成为根的子树。
2.结点分类:结点拥有的子树称为结点的度。度为0的结点称为叶结点或终端节点;度不为0的结点称为非终端结点或分支结点。除根结点以外,分支节点也称为内部结点。树的度是树内部各结点的度的最大值。
3.结点间的关系:结点的子树的根称为该结点的孩子,相应的,该结点称为孩子的双亲。同一个双亲的孩子互称兄弟。结点的祖先是从根结点所经分支上的所有结点。以某结点为根的子树中的任意结点都成为该结点的孙子。
4.结点的层次从根开始定义,树中结点最大层次成为树的深度或高度。
森林是m棵互不相交的树的集合。
5.二叉树:它是结点的有限集合,这个集合或者为空集或者由一个根及两棵不相交的分别称作这个根的左右子树的二叉树组成。
特点:每个结点至多由两棵子树(即不存在度大于二的结点);二叉树的子树由左右之分,且次序不能任意颠倒,只有一棵子树时也必须分清左右子树。
6.二叉树的性质:
(1)一个非空二叉树的第i层上至多有2i-1个结点
(2)深度为k的二叉树至多有2k-1个结点
(3)对任何一棵非空二叉树T,如果叶结点数为n0,度为2的结点为n2,则n0=n2+1;
度:n=n0+n1+n2; 分支:n-1=2n2+n1;
7.满二叉树:深度为k且有2k-1个结点的二叉树,不存在度为1的点
8.完全二叉树:深度为k,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树编号从1到n的结点完全对应时,称为完全二叉树。
特点:叶子结点只可能出现在层次最大的前两层上出现。
若节点无左子树,则没有右子树
性质:
9.二叉树的存储结构
(1) 顺序存储结构
实现:按满二叉树的结点层次编号,依次存放二叉树中的数据元素。
特点:结点间关系蕴含在其存储位置中;浪费空间,适于存储满二叉树和完全二叉树。
(2)链式存储结构(二叉链表、三叉链表)
二叉链表:
typedef struct BiNode
{
Elemtype data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
在n个节点的二叉链表中,有n+1个空指针域
10.二叉树构建
int CreateTree(BiTree &T)
{
char c;
scanf("%c",&c);
if(c=='*')T=NULL;
else
{
T=(BiTree)malloc(sizeof(BiNode));
T->data=c;
CreateTree(T->left);
CreateTree(T->right);
}
}
11.二叉树前序、中序、后序遍历(递归)
void PreOrderTree(BiTree T)
{
if(T)
{
printf("%c ",T->data);
PreOrderTree(T->left);
PreOrderTree(T->right);
}
}
void InOrderTree(BiTree &T)
{
if(T)
{
InOrderTree(T->left);
printf("%c ",T->data);
InOrderTree(T->right);
}
}
void PostOrderTree(BiTree &T)
{
if(T)
{
PostOrderTree(T->left);
PostOrderTree(T->right);
printf("%c ",T->data);
}
}
12.二叉树前序、中序、后序遍历(非递归)
void preorder(BiTree T)
{
SqStack S;S.top=-1;
BiTree p=T;
while(p||S.top!=-1)
{
while(p)
{
printf("%c ",p->data);
Push(S,p);
p=p->left;
}
if(S.top!=-1)
{
Pop(S,p);
p=p->right;
}
}
}
void inorder(BiTree &T)
{
SqStack S;S.top=-1;
BiTree p=T;
while(p||S.top!=-1)
{
while(p)
{
Push(S,p);
p=p->left;
}
if(S.top!=-1)
{
Pop(S,p);
printf("%c ",p->data);
p=p->right;
}
}
}
后序遍历需要重新定义栈
typedef struct
{
BiTree t;
int isfirst;
}Dstruct;
typedef struct
{
Dstruct data[MAXSIZE];
int top;
}SqStack;
void postorder(BiTree T)
{
SqStack S;S.top=-1;
Dstruct d;
BiTree p=T;
while(p||S.top!=-1)
{
while(p)
{
d.isfirst=1;
d.t=p;
Push(S,d);
p=p->left;
}
if(S.top!=-1)
{
Pop(S,d);
if(d.isfirst==1)
{
d.isfirst=0;
p=d.t;
Push(S,d);
p=p->right;
}
else
{
printf("%c ",d.t->data);
p=NULL;
}
}
}
}
求中序的第一个结点的算法
p=T;
while(p->left)
p=p->left;
printf("%c ",p->data);
求中序的最后一个结点的算法
p=T;
while(p->right)
p=p->right;
printf("%c ",p->data);
已知一棵树的先序、后序或层次序列结合中序,可以唯一确定一棵二叉树。
13.找出满足下列条件的二叉树
先序序列和后序序列相同
DLR和LRD相同——–只有一个根结点或空树
先序序列和中序序列相同
DLR和LDR相同——–任何一个结点无左子树
中序序列和后序序列相同
LDR和LRD相同——–任何一个结点无右子树
中序序列和层次序列相同
LDR和层次序列相同–任何一个结点无左子树
13.求二叉树深度的算法
int Depth(BiTree T)
{
int depl,depr;
if(T==NULL)
return 0;
else
{
depl=Depth(T->left);
depr=Depth(T->right);
if(depl>depr)return depl+1;
else return depr+1;
}
}
求二叉树结点的个数
int Size(BiTree T)
{
if(!T)
return 0;
else return Size(T->left)+Size(T->right)+1;
}
二叉树叶子结点个数
int leafCount(BiTree T)
{
if(!T)
return 0;
else
if(!T->left&&!T->right) return 1;
else return leafCount(T->left)+leafCount(T->right);
}
int leaf=0;
void leafnum(BiTree T)
{
if(T)
{
leafnum(T->left);
if(!T->left&&!T->right)
leaf++;
leafnum(T->right);
}
}
复制二叉树
BiTree Copy(BiTree T)
{
BiTree p;
if(T)
{
p=(BiTree)malloc(sizeof(BiNode));
p->data=T->data;
p->left=Copy(T->left);
p->right=Copy(T->right);
return p;
}
}
层次遍历(非递归)
void LevelOrder(BiTree T)
{
BiTree p=T;
SqQueue Q;
Q.rear=Q.front=0;
EnQueue(Q,T);
while(Q.rear!=Q.front)
{
DnQueue(Q,p);
printf("%c ",p->data);
if(p->left)
EnQueue(Q,p->left);
if(p->right)
EnQueue(Q,p->right);
}
}
已知中序先序遍历序列构造二叉树
BiTree CreateBiTree(char pre[],char in[],int l1,int r1,int l2,int r2)
{
BiTree s;
int i;
if(l1>r1)return NULL;
s=(BiTree)malloc(sizeof(BiNode));
s->lchild=s->rchild=NULL;
for(i=l2;i<=r2;i++)
if(in[i]==pre[l1])
break;
s->data=in[i];
s->lchild=CreateBiTree(pre,in,l1+1,l1+i-l2,l2,i-1);
s->rchild=CreateBiTree(pre,in,l1+i-l2+1,r1,i+1,r2);
return s;
}