如果用链表来存储二叉树,那么可以将二叉树定义如下:
typedef char ElemType;
typedef struct node{
ElemType data; //数据元素
struct node* lchild; //指向左孩子
struct node* rchild; //指向右孩子
}BTNode;
问题一:二叉树的深度
二叉树的深度,也叫二叉树的高度,二叉树的深度等于从根结点到叶子结点的最长路径加1。用递归的观点来看,二叉树的深度,等于其最大左右子树的深度加1,而每个左子树(右子树)又可以分解为次左子树+次右子树,它们是深度也是最大子树深度加1。也就是二叉树深度的递归模型f(b)如下:
{
f
(
b
)
=
0
,
若b=NULL
f
(
b
)
=
M
a
x
{
f
(
b
−
>
l
c
h
i
d
)
,
f
(
b
−
>
r
c
h
i
l
d
)
}
+
1
,
其他情况
\begin{cases} f(b)=0, & \text{若b=NULL} \\ f(b)=Max\{f(b->lchid),f(b->rchild)\}+1, & \text{其他情况} \end{cases}
{f(b)=0,f(b)=Max{f(b−>lchid),f(b−>rchild)}+1,若b=NULL其他情况
对应的递归算法如下:
//求二叉树b的深度
int BTNodeDepth(BTNode *b){
int lchilddep,rchilddep;
if(b==NULL)
return 0;
else{
lchilddep=BTNodeDepth(b->lchild);
rchilddep=BTNodeDepth(b->rchild);
return (lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
}
}
问题二:二叉树的宽度
二叉树的宽度:具有结点数最多的那一层的结点个数。
采用分层遍历的方法求出所有结点的层编号,然后,求出各层的结点总数,通过比较找出层结点数最多的值。对应的算法如下:
//求二叉树b的宽度
int BTWidth(BTNode *b){
struct{
int lno; //结点的层次编号
BTNode *p; //结点指针
}Qu[MaxSize]; //定义顺序非循环队列
int front,rear;
int lnum,max,i,n;
front=rear=0; //置队列为空
if (b!=NULL)
{
rear++;
Qu[rear].p=b; //根结点指针入队
Qu[rear].lno=1; //根结点的层次编号为1
while (rear!=front) //队列不为空
{
front++;
b=Qu[front].p; //队头出队
lnum=Qu[front].lno;
if (b->lchild!=NULL) //左孩子入队
{
rear++;
Qu[rear].p=b->lchild;
Qu[rear].lno=lnum+1;
}
if (b->rchild!=NULL) //右孩子入队
{
rear++;
Qu[rear].p=b->rchild;
Qu[rear].lno=lnum+1;
}
}
max=0; lnum=1; i=1;
while (i<=rear)
{
n=0;
while (i<=rear && Qu[i].lno==lnum)
{
n++; i++;
}
lnum=Qu[i].lno;
if(n>max) max=n;
}
return max;
}
else
return 0;
}
问题三:二叉树b的叶子结点个数
当b为空树时,叶子结点数为0;
当b的左子树和右子树都为空,b只有一个结点时,叶子结点数为1;
当b的左子树或右子树不为空时,叶子结点数=左子树叶子结点数+右子树叶子结点数。
即递归模型为:
{ f ( b ) = 0 , 若b=NULL f ( b ) = 1 , 若b->lchild==NULL且b->rchild==NULL f ( b ) = f ( b − > l c h i l d ) + f ( b − > r c h i l d ) , 其他情况 \begin{cases} f(b)=0, & \text{若b=NULL} \\ f(b)=1, & \text{若b->lchild==NULL且b->rchild==NULL} \\ f(b)=f(b->lchild)+f(b->rchild), & \text{其他情况} \end{cases} ⎩⎪⎨⎪⎧f(b)=0,f(b)=1,f(b)=f(b−>lchild)+f(b−>rchild),若b=NULL若b->lchild==NULL且b->rchild==NULL其他情况
对应的递归算法如下:
//求二叉树b的叶子结点个数
int LeafNodes(BTNode *b){
int num1,num2;
if(b==NULL)
return 0;
else if(b->lchild==NULL && b->rchild==NULL)
return 1;
else{
num1=LeafNodes(b->lchild);
num2=LeafNodes(b->rchild);
return (num1+num2);
}
}
完整代码如下:
//BinaryTreeBase.h
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node{
ElemType data; //数据元素
struct node* lchild; //指向左孩子
struct node* rchild; //指向右孩子
}BTNode;
//由str串创建二叉链
void CreateBTNode(BTNode *&b,char *str){
BTNode *St[MaxSize],*p=NULL;
int top=-1,k,j=0;
char ch;
b=NULL;
ch=str[j];
while (ch!='\0')
{
switch(ch){
case '(': top++; St[top]=p; k=1; break;
case ')': top--; break;
case ',': k=2; break;
default: p=(BTNode *)malloc(sizeof(BTNode));
p->data=ch; p->lchild=p->rchild=NULL;
if(b==NULL)
b=p;
else{
switch(k){
case 1: St[top]->lchild=p; break;
case 2: St[top]->rchild=p; break;
}
}
}
j++;
ch=str[j];
}
}
//返回data域为x的结点指针
BTNode *FindNode(BTNode *b,ElemType x){
BTNode *p;
if(b==NULL)
return NULL;
else if(b->data==x)
return b;
else{
p=FindNode(b->lchild,x);
if(p!=NULL)
return p;
else
return FindNode(b->rchild,x);
}
}
BTNode *LchildNode(BTNode *p){
return p->lchild;
}
BTNode *RchildNode(BTNode *p){
return p->rchild;
}
//求二叉树b的深度
int BTNodeDepth(BTNode *b){
int lchilddep,rchilddep;
if(b==NULL)
return 0;
else{
lchilddep=BTNodeDepth(b->lchild);
rchilddep=BTNodeDepth(b->rchild);
return (lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
}
}
//用括号表示法输出二叉树
void DispBTNode(BTNode *b){
if (b!=NULL)
{
printf("%c",b->data);
if (b->lchild!=NULL || b->rchild!=NULL)
{
printf("(");
DispBTNode(b->lchild);
if(b->rchild!=NULL) printf(",");
DispBTNode(b->rchild);
printf(")");
}
}
}
void printBTN(BTNode *b,int w){
int i;
if (b!=NULL)
{
printBTN(b->rchild,w+5);
for(i=1;i<w;i++)
printf(" ");
printf("%c\n",b->data);
printBTN(b->lchild,w+5);
}
}
//求二叉树b的宽度
int BTWidth(BTNode *b){
struct{
int lno; //结点的层次编号
BTNode *p; //结点指针
}Qu[MaxSize]; //定义顺序非循环队列
int front,rear;
int lnum,max,i,n;
front=rear=0; //置队列为空
if (b!=NULL)
{
rear++;
Qu[rear].p=b; //根结点指针入队
Qu[rear].lno=1; //根结点的层次编号为1
while (rear!=front) //队列不为空
{
front++;
b=Qu[front].p; //队头出队
lnum=Qu[front].lno;
if (b->lchild!=NULL) //左孩子入队
{
rear++;
Qu[rear].p=b->lchild;
Qu[rear].lno=lnum+1;
}
if (b->rchild!=NULL) //右孩子入队
{
rear++;
Qu[rear].p=b->rchild;
Qu[rear].lno=lnum+1;
}
}
max=0; lnum=1; i=1;
while (i<=rear)
{
n=0;
while (i<=rear && Qu[i].lno==lnum)
{
n++; i++;
}
lnum=Qu[i].lno;
if(n>max) max=n;
}
return max;
}
else
return 0;
}
//求二叉树b的结点个数
int Nodes(BTNode *b){
int num1,num2;
if(b==NULL)
return 0;
else if(b->lchild==NULL && b->rchild==NULL)
return 1;
else{
num1=Nodes(b->lchild);
num2=Nodes(b->rchild);
return (num1+num2+1);
}
}
//求二叉树b的叶子结点个数
int LeafNodes(BTNode *b){
int num1,num2;
if(b==NULL)
return 0;
else if(b->lchild==NULL && b->rchild==NULL)
return 1;
else{
num1=LeafNodes(b->lchild);
num2=LeafNodes(b->rchild);
return (num1+num2);
}
}
//主函数.cpp
#include "BinaryTreeBase.h"
#include <stdio.h>
#include <stdlib.h>
void main()
{
BTNode* bt;
char str[20]="A(B(D(,G)),C(E,F))";
CreateBTNode(bt,str);
printf("二叉树的括号表示法:");
DispBTNode(bt);
printf("\n");
printf("横向打印二叉树:\n");
printBTN(bt,10);
printf("\n");
int num=0,leafNum=0,deepth=0,width=0;
num=Nodes(bt);
leafNum=LeafNodes(bt);
deepth=BTNodeDepth(bt);
width=BTWidth(bt);
printf("二叉树的结点数: %d\n",num);
printf("二叉树的叶子结点数: %d\n",leafNum);
printf("二叉树的深度: %d\n",deepth);
printf("二叉树的宽度: %d\n",width);
system("pause");
}
效果如下:
