求二叉树的深度、宽度和叶子结点数

57 篇文章 1 订阅
53 篇文章 2 订阅

如果用链表来存储二叉树,那么可以将二叉树定义如下:

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=NULLb->lchild==NULLb->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");
}

效果如下:

图(1) 用括号表示法,创建二叉树,并求它的深度、宽度和叶子结点数
图(1) 用括号表示法,创建二叉树,并求它的深度、宽度和叶子结点数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanqima

一键三连,多多益善

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值