二叉树:求树的高度(递归和非递归算法)

题目:假设二叉树采用二叉链表存储结构,设计一个算法求二叉树的高度。

递归

分析:用递归方式来实现比较抽象,有一种没有解决问题的错觉。如果要理解递归,就要理解递归。。。但是递归的代码量少,简洁。如图,要以一种抽象化的方式来理解。不能具体,一旦具体了,就跟啥都没解决似的。
在这里插入图片描述

算法思想:递归左子树高度和右子树的高度,取较大者+1。
代码

int BTdepth(BiTree T){  // 求树的高度depth
	if(T!=NULL)  // 空树的高度为零
		return 0;
	ldepth=BTdepth(T->lchild);  // 求左孩子的高度
	rdepth=BTdepth(T->rchild);  // 求右孩子的高度
	if(ldepth>rdepth) 
		ldepth=ldepth+1;  
		// 树的高度为最大高度的子树加个根结点
		return ldepth;
	else
		rdepth=rdepth+1;
		return rdepth;
}

非递归

分析:非递归比较难理解,是在层次遍历的基础上进行改造,也是借助队列完成。那么如何要求出树的高度?可以让一个变量last始终指向每一层最右端的结点,指了几个结点,就有几层,即二叉树的高度。
如图,rear指向入队的结点,front指向要出队的结点,last指向当前层最右端的结点。last是一个普通的变量,值为0,rear和front是队列的,指向-1。在这里插入图片描述
根结点A入队,rear指向A
在这里插入图片描述
然后front前进一步,front指向A,A出队,访问,A有BC两个左右孩子,BC入队,front等于last,所以将last指向rear。注意只要front等于last了,就将last指向rear。在这里插入图片描述
在这里插入图片描述

然后front前进一步,front指向B,B出队,访问,B有DE两个左右孩子,DE入队。
front前进一步,指向C,C没有左右孩子,C直接出队。
rear指向最后入队结点E。
此时front等于last,所以将last指向rear。在这里插入图片描述
front往前走一步,指向D,D没有左右孩子,直接出队。
在这里插入图片描述
front向前走一步,指向E,E出队,访问,发现E有FG两个左右孩子,将FG入队,rear指向G,此时front=last,所以将last指向rear指向的结点。
在这里插入图片描述
front前进一步,指向F,没有左右孩子,直接出队;
front再前进一步,指向G,没有左右孩子,直接出队;
此时front=rear,结束循环,最终rear分别指向过ACEG,恰好是每层最右端的结点,结点个数为4,所以此二叉树的高度为4。
在这里插入图片描述
总结:rear指向每次入队的最后结点,front每次向前走一步,当fronreat时lastrear。这就是核❤思想。然后层数level加1,最后level的值就是二叉树的高度。

算法思想:采用层次遍历的算法,设置变量level记录当前结点所在的层数,设置变量last指向当前层的最右结点,每次层次遍历出队时与last指针比较,若两者相等,则层数加1,并让last指向下一层最右端的结点,直到遍历完成。level的值即为二叉树的高度。核❤问题在于如何让last指向每层最右端的结点。

代码

int BTdepth(BiTree T){
	if(T==NULL)  // 空树的高度为0
		return 0;
	int front=-1,rear=-1;  // 初始化一个空的队列
	int last=0,level=0;  
	// last指向当前层的最右结点,level记录树的层数
	BiTree Q[MaxSize];  // 假设队列足够大
	Q[++rear]=T;  // 根结点入队
	BiTree p;  // 初始化指针p
	while(front<rear){  
	// 队列不空,则循环
	// fornt<rear说明有入队的操作,队列不空
		p=Q[++front];  
		// front指向要出队的结点
		// 当前front指向的队列元素出队并访问
		if(p->lchild)  // 如果有左孩子
			Q[++rear]=p->lchild;  // 左孩子入队
		if(p->rchild)  // 如果有右孩子
			Q[++rear]=p->rchild;  // 右孩子入队
		if(front==rear){  // ❤
			level++;  // 层数加1
			last=rear;  // ❤
		}
	}
	return level;
}
  • 27
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

花间半盘棋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值