求二叉树中的结点个数、叶子结点个数以及某结点的层次和二叉树的宽度

课程设计题目

求二叉树中的结点个数、叶子结点个数以及某结点的层次和二叉树的宽度


课程设计目的

掌握二叉树遍历算法的应用,熟练使用先序、中序、后序 3 种递归遍历算法和层次遍历算法进行二叉树问题的求解。


问题描述

编写一个程序 exp7-6.cpp 实现以下功能

(1) 输出二叉树b的结点个数。

(2) 输出二叉树b的叶子结点个数。

(3) 求二叉树 b中指定结点值(假设所有结点值不同)的结点的层次

(4) 利用层次遍历求二叉树 b 的宽度。


数据结构及算法设计

二叉树是一种非线性的数据结构,它由节点和连接节点的边组成。每个节点都有一个值,通常称为键或关键字。二叉树可以是空的,也可以有一个根节点和两个子节点(左子树和右子树)。

        1. 输出二叉树b的结点个数:可以使用递归的方法遍历整个二叉树,每遍历一个节点就将计数器加1,直到遍历完整个二叉树。

        2. 输出二叉树b的叶子结点个数:同样使用递归的方法遍历整个二叉树,当遇到叶子节点时(即左右子树都为空),将计数器加1。

        3. 求二叉树 b 中指定结点值的结点的层次:首先找到指定值的节点,然后从根节点开始进行层次遍历,记录遍历到该节点的层数。

        4. 利用层次遍历求二叉树 b 的宽度:使用队列来实现层次遍历,每次遍历一层时,记录当前层的节点数,最后取最大值作为二叉树的宽度。


源程序 

//二叉树的基本运算算法
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node 
{	
	ElemType data;			//数据元素
	struct node *lchild;	//指向左孩子结点
	struct node *rchild;	//指向右孩子结点
} BTNode;
void CreateBTree(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')  	//str未扫描完时循环
	{
   	   	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)                    	 	//*p为二叉树的根结点
					b=p;
				else  								//已建立二叉树根结点
				{	
					switch(k) 
					{
					case 1:St[top]->lchild=p;break;
					case 2:St[top]->rchild=p;break;
					}
				}
		}
		j++;
		ch=str[j];
	}
}
void DestroyBTree(BTNode *&b)	//销毁二叉树
{	if (b!=NULL)
	{	DestroyBTree(b->lchild);
		DestroyBTree(b->rchild);
		free(b);
	}
}
BTNode *FindNode(BTNode *b,ElemType x) //查找值为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;
}
int BTHeight(BTNode *b)		//求二叉树b的高度
{
   	int lchildh,rchildh;
   	if (b==NULL) return(0); 				//空树的高度为0
   	else  
	{
		lchildh=BTHeight(b->lchild);	//求左子树的高度为lchildh
		rchildh=BTHeight(b->rchild);	//求右子树的高度为rchildh
		return (lchildh>rchildh)? (lchildh+1):(rchildh+1);
   	}
}
void DispBTree(BTNode *b)  //以括号表示法输出二叉树
{
	if (b!=NULL)
	{	printf("%c",b->data);
		if (b->lchild!=NULL || b->rchild!=NULL)
		{	printf("(");						//有孩子结点时才输出(
			DispBTree(b->lchild);				//递归处理左子树
			if (b->rchild!=NULL) printf(",");	//有右孩子结点时才输出,
			DispBTree(b->rchild);				//递归处理右子树
			printf(")");						//有孩子结点时才输出)
		}
	}
}


int Nodes(BTNode *b)	//求二叉树b的结点个数
{
    int num1,num2;
    if (b==NULL) // 如果当前节点为空,返回0
        return 0;
    else if (b->lchild==NULL && b->rchild==NULL) // 如果当前节点是叶子节点,返回1
        return 1;
    else // 否则,递归计算左子树和右子树的结点个数,并加上当前节点(即1)
    {
        num1=Nodes(b->lchild); // 计算左子树的结点个数
        num2=Nodes(b->rchild); // 计算右子树的结点个数
        return (num1+num2+1); // 返回总的结点个数
    }
}
int LeafNodes(BTNode *b)	//求二叉树b的叶子结点个数
{
    int num1,num2;
    if (b==NULL) // 如果当前节点为空,返回0
        return 0;
    else if (b->lchild==NULL && b->rchild==NULL) // 如果当前节点是叶子节点,返回1
        return 1;
    else // 否则,递归计算左子树和右子树的叶子结点个数,并加上当前节点(即1)
    {
        num1=LeafNodes(b->lchild); // 计算左子树的叶子结点个数
        num2=LeafNodes(b->rchild); // 计算右子树的叶子结点个数
        return (num1+num2); // 返回总的叶子结点个数
    }
}
int Level(BTNode *b,ElemType x,int h)	//求二叉树b中结点值为x的结点的层次
{	int l;
    if (b==NULL) // 如果当前节点为空,返回0
        return(0);
    else if (b->data==x) // 如果当前节点的值等于x,返回当前层次h
        return(h);
    else // 否则,递归在左子树中查找,如果未找到,再在右子树中查找
    {	l=Level(b->lchild,x,h+1);	//在左子树中查找
        if (l!=0) // 如果找到了,返回结果
            return(l);
        else						//在左子树中未找到,再在右子树中查找
            return(Level(b->rchild,x,h+1));
    }
}

int BTWidth(BTNode *b)					//求二叉树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;				//出队结点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;				//max存放宽度
        while (i<=rear)
        {
            n=0;
            while (i<=rear && Qu[i].lno==lnum) //i扫描队列中所有结点
            {
                n++;					//n累计一层中的结点个数
                i++;
            }
            lnum=Qu[i].lno;
            if (n>max) max=n;
        }
        return max;
    }
    else return 0;
}
int main()
{
    ElemType x='K';
    BTNode *b,*p,*lp,*rp;
    CreateBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
    printf("输出二叉树b:");DispBTree(b);printf("\n");
    printf("二叉树b的结点个数:%d\n",Nodes(b));
    printf("二叉树b的叶子结点个数:%d\n",LeafNodes(b));
    printf("二叉树b中值为%c结点的层次:%d\n",x,Level(b,x,1));
    printf("二叉树b的宽度:%d\n",BTWidth(b));
    DestroyBTree(b);
    return 1;
}

数据及结果分析

在实验中,通过构建二叉树并使用不同的遍历算法,得到了二叉树的结点个数、叶子结点个数、指定结点的层次和二叉树的宽度。


体会

通过实验求二叉树中的结点个数、叶子结点个数以及某结点的层次和二叉树的宽度,可以帮助我们更好地理解二叉树的性质和操作方法。

        1. 理解二叉树的基本概念:在进行实验之前,我们需要充分理解二叉树的基本概念,如根节点、叶子节点、度、深度等。这些概念是求解问题的基础,只有对它们有了清晰的认识,才能更好地进行实验。

        2. 掌握二叉树的基本操作:实验中涉及到的操作主要包括创建二叉树、遍历二叉树、查找结点等。我们需要熟练掌握这些基本操作,以便在实验中使用。

        3. 递归思想的运用:在求解二叉树中的结点个数、叶子结点个数以及某结点的层次时,我们通常会使用递归思想。通过递归调用函数,可以简化代码实现,提高代码的可读性。

        4. 注意边界条件的处理:在进行实验时,我们需要注意处理一些边界条件,如空树、只有一个结点的树等。这些特殊情况需要单独处理,不能简单地套用公式或算法。

        5. 二叉树宽度的计算:在计算二叉树的宽度时,我们需要找到最宽的一层。这可以通过遍历二叉树的所有层来实现。在遍历过程中,我们需要记录每一层的最大宽度,最后得到的结果即为所求的二叉树宽度。

        6. 结果输出与分析:实验完成后,我们需要对结果进行输出和分析。通过对结果的分析,我们可以了解二叉树的一些性质,如高度、结点个数与叶子结点个数的关系等。这有助于我们更深入地理解二叉树。

        总之,通过做这个实验,我不仅巩固了二叉树的基本知识,还提高了自己的编程能力和分析问题的能力。在今后的学习中,我将继续努力,探索更多关于数据结构的知识。

  • 29
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

万叶学编程

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值