求二叉樹的深度、寬度和葉子結點數
阿新 • • 發佈:2019-01-29
如果用連結串列來儲存二叉樹,那麼可以將二叉樹定義如下:
typedef char ElemType;
typedef struct node{
ElemType data; //資料元素
struct node* lchild; //指向左孩子
struct node* rchild; //指向右孩子
}BTNode;
問題一:二叉樹的深度
二叉樹的深度,也叫二叉樹的高度,二叉樹的深度等於從根結點到葉子結點的最長路徑加1。用遞迴的觀點來看,二叉樹的深度,等於其最大左右子樹的深度加1,而每個左子樹(右子樹)又可以分解為次左子樹+次右子樹,它們是深度也是最大子樹深度加1。也就是二叉樹深度的遞迴模型f(b)如下: 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的左子樹或右子樹不為空時,葉子結點數=左子樹葉子結點數+右子樹葉子結點數。
即遞迴模型為:
對應的遞迴演算法如下:
//求二叉樹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>
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);
}
效果如下: