二叉树层次遍历BFS求最大宽度习题

例6-5

假设二叉树采用二叉链表存储结构存储,设计一个算法,求出该二叉树的宽度(拥有节点数最多的那一层的节点个数)

思路: 要求结点数最多的一层,可以分别求出每层的节点数,然后从中选取最多的,要达到这个目的,需要明白两件事:
第一:对于非空树,树根所在的层位第一层,并且从层次遍历算法的程序中可以看出,有一个由当前节点找到其左右孩子节点的操作。这就提示我们,如果知道当前节点的层号,就能推出其左右孩子的层号,即当前节点的层号+1,进而可以求出所有结点的层号
第二:在层次遍历中,用到了一个循环队列(队列用数组表示的),其出对和入队操作:front=(front+1)%MaxSize, rear=(rear+1)%MaxSize。如果用来存队列的数组足够长,足以容纳树中所有的结点,那就不会出现假溢出的情况,那就可以不用循环队列,用++rear, ++front代替。这样的话,访问的所有结点不存在覆盖的情况,所有节点都保存在数组中。再给这个数组一个层号,如果这个层号是某一层时,一个计数n++,直到这个层全找完为止。

typedef struct BTNode{
	int data;
	struct BTNode * lchild;
	struct BTNode * rchild; 
}BTNode;
typedef struct{
	BTNode * p;		//结点指针 
	int lno;		//节点所在层次号 
}St;
int maxNode(BTnode *b){
	St que[MaxSize];		//定义顺序非循环队列 
	int front,rear=0;
	int Lno=0,i,j,n,max=0;
	front=rear=0;
	BTNode * q;
	if(b!=NULL){
		++rear;
		que[rear].p=b;		//树根入队
		que[rear].lno=1;		//树根所在层次号设为1
		while(front!=rear){
			++front;
			q=que[front].p;
			Lno=que[front].lno;	//关键语句:Lno用来存取当前节点的层次号
			if(q->lchild!=NULL){
				++rear;
				q=que[rear].p=q->lchild;
				que[rear].lno=Lno+1;	//关键语句:根据当前结点的层次号推知其孩子 结点的层次号
				if(q->rchild!=NULL){
					++rear;
					que[rear].p=q->rchild;
					que[rear].lno=Lno+1; 	//关键语句:根据当前结点的层次号推知其孩子 结点的层次号
				} 
			}
			//注意:循环结束后,Lno中保存的时这棵二叉树的最大层数
			/*以下代码找出了含有节点最多的层中的节点数*/
			max=0;
			for(i=1;i<Lno;++i){
				n=0;						//每一层都对应n,每次都得给他清零
				for(j=0;j<rear;++j)			//循环遍历每个数组元素,一共有rear个
					if(que[j].lno==i)		//如果遍历的元素的层数==某一层,
						++n;				//计数++ 
					if(max<n)
						max=n;
			}
			return max; 
		}
		else return 0;		//空树直接返回0 
	}
}

先定义了一个基础的BTNode,在定义了一个结构体,这个结构体包含了BTNode这个结点,也包含了层数。用这个新结构体定义一个数组类型的结构体,这样,每一个节点都对应了一个层数。
也没什么太难的操作,就是给根节点了一个层数Lno = 1,然后正常的找左右孩子入队,然后把层数在原来上一层的基础上++。操作完成后,St数组里存满了元素,对应着也有层号。一共有多少层呢?front是出队列,虽然出,但是元素还是在数组里面的,而rear却是一直往后移动的,所以rear = 节点的个数,又只Lno保存的是当前节点的层数,循环结束后,Lno保存的就是最大层数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值