层序遍历的应用——求树高、树宽

本文介绍了如何利用栈和队列进行树的遍历,包括层序遍历、计算树的高度、宽度以及判断是否为完全二叉树的方法。层序遍历借助队列实现,树高和宽度通过遍历节点并维护层级信息来计算,完全二叉树的判断则关注非叶子节点的入队顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


由于在考研的算法题中,栈/队列一般都是通过在函数中设立数组完成(顺序,链式一般不用),所以以后的栈/队列都在用数组操作完成。

层序遍历

层序遍历需要借助队列,根先入队,然后每次出队一个结点,若其有左/右结点,就将其左/右结点入队。这样出队的顺序就是按照从上到下,从左到右的层序遍历顺序。

void LevelOrder3(BiTree T) {
	BiTree Q[100];   //假设足够大
	int front = 0, rear = 0;
	BiNode* p;
	Q[rear++] = T;        //根先入队
	while (front != rear) {
		p = Q[front++];    //出队
		cout << p->data;
		if (p->lchild)
			Q[rear++] = p->lchild;    //左子入队
		if (p->rchild)
			Q[rear++] = p->rchild;    //右子入队
	}
}

1.树高——递归、层序、后序

层序求法:
设立遍历level=0last=1,分别记录层数和左右边结点编号,根为1.
初始时front=rear=0
每当front==last时,说明已经有一层出队了(队内保存的是下一层的所有结点),此时level++,并且更新last=rear,再去出队下一层。

int Depth(BiTree T) {

	BiTree Q[100];
	int front = 0, rear = 0;
	int level = 0, last = 1;   //因为每出一层,level++,所以初始level=0
	Q[rear++] = T;   //根入队
	BiNode* p;
	while (front != rear) {
		p = Q[front++];
		if (p->lchild)
			Q[rear++] = p->lchild;
		if (p->rchild)
			Q[rear++] = p->rchild;
		if (front == last) {      //当最右边结点出队,进行操作,此时队内是下一层所有结点
			level++;
			last = rear;
		}
	}
	return level;
}

2.树宽

依旧设立last=1,记录每次最右边的结点,设立nums=1,记录从第二层开始每层结点数最大值,初始值为1
因为每次最右边结点出队时,若front==last,进行操作,此时队内是下一层结点,所以我们只能从第二层开始计数,第一层其实必然是1。

int Width(BiTree T) {
	if (T == NULL)
		return 0;
	BiTree Q[100]; //队列
	int front = 0, rear = 0;     //front指向队首,rear指向队尾后一个
	int nums = 1, last = 1;    //从第二层开始计数,nums初始值为第一层结点数1,last初始值为第一层左右结点编号
	Q[rear++] = T;		 //根进队
	BiNode* p;
	while (front != rear) {
		p = Q[front++];
		if (p->lchild)
			Q[rear++] = p->lchild;
		if (p->rchild)
			Q[rear++] = p->rchild;
		if (front == last) {	//每出队完了一层结点(出队的p是最右边的结点),那么来计数队内结点数(从第二层开始)
			nums = nums > rear - front ? nums : rear - front;  
			last = rear;  //更新last
		}
	}
	return nums;
}

3.判断是否为完全二叉树

我们每次入队时,若p!=NULL,直接让左右子树都入队。

  1. 如果是完全二叉树,那么队内必然没有NULL,或者NULL是最后一个进队的叶子(也是出队的)。
  2. 如果是非完全二叉树,则必然在最后一个元素之前会有NULL进队,然后出队。

我们只需要判断,如果有NULL出队,其如果不是最后一个元素(即其后队内还有其他元素),那么就是非完全二叉树。

bool Q7(BiTree T) {
	BiTree Q[100];
	int front = 0, rear = 0;
	Q[rear++] = T;
	BiNode* p;
	while (front != rear) {
		p = Q[front++];
		if (p) {
			Q[rear++] = p->lchild;       //左右子不判断,直接入队
			Q[rear++] = p->rchild;
		}
		else {
			while (front != rear) {    //若队内有空,且不是最后一个,即非完全
				p = Q[front++];
				if (p)
					return 0;
			}
		}
	}
	return 1;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值