一、二叉树的宽度优先遍历

二叉树的宽度优先遍历,又叫广度优先遍历、层序优先遍历。

二叉树的宽度优先遍历可以使用队列完成。

算法步骤:

1)二叉树根节点进入队列;

2)弹出并输出队首节点;

3)将队首节点的左孩子节点和右孩子节点依次压进队列;

4)循环执行2)3)步,直到队列为空;

代码实现:

void widthTraversal(TreeNode* root)
{
	if (nullptr == root)
	{
		return;
	}
	queue<TreeNode*> nodeQueue;
	nodeQueue.push(root);
	while (!nodeQueue.empty())
	{
		TreeNode* temp = nodeQueue.front();
		//弹出队首节点
		nodeQueue.pop();
		//打印队首节点,并获取其左孩子节点和右孩子节点进入队列
		cout << temp->val << endl;
		if (nullptr != temp->left)
		{
			nodeQueue.push(temp->left);
		}
		if (nullptr != temp->right)
		{
			nodeQueue.push(temp->right);
		}
	}
}

二、【题目】求二叉树的最大宽度

题目解析:

如题,求一个二叉树的最大宽度。上面我们实现了二叉树的宽度遍历,即相同层级的节点肯定是依次输出遍历的。我们可以根据这一点,适当修改上述函数就可以实现本题。

算法解析:

1)、首先,我们需要知道每一个节点的层数:每一个节点的层数是其父节点层数+1

所以,我们在push一个节点的孩子节点进入队列时,可以保存其孩子节点的层级:当前层级+1。

2)、其次,我们需要获取每一层的宽度,并所有层级宽度取最大值返回。因为宽度遍历方式相同层级的节点肯定是依次输出遍历,我们就很方便对某层宽度进行计数。

这两个难点都解决了,解题就很很容易了。见代码

代码实现:

int MaxWidth(TreeNode* root)
{
	int widMax = 0; //记录结果:最大宽度
	if (nullptr == root)
	{
		return 0;
	}
	queue<TreeNode*> nodeQueue; //遍历二叉树的辅助队列
	unordered_map< TreeNode*, int> levelMap; //记录每个节点所在层数的哈希表
	//根节点入队列
	nodeQueue.push(root);
	levelMap[root] = 1; //根节点定义为在第1层
	int curLevel = 1; //当前所在层数
	int curWidth = 0; //当前层记录的宽度
	while (!nodeQueue.empty())
	{
		TreeNode* temp = nodeQueue.front();
		//弹出队首节点
		nodeQueue.pop();
		//获取队首节点的层数,如果和上一个队首节点的层数curLevel相同,则curWidth+1;否则,说明已经开始进入下一层,则重置curWidth并更新curLevel
		if (levelMap[temp] == curLevel)
		{
			++curWidth;
		}
		//已经进入下一层
		else
		{
			widMax = curWidth > widMax ? curWidth : widMax;
			curWidth = 1;
			curLevel = levelMap[temp];
		}

		if (nullptr != temp->left)
		{
			nodeQueue.push(temp->left);
			//保存当前节点左孩子的层数:当前层数+1
			levelMap[temp->left] = curLevel + 1;
		}
		if (nullptr != temp->right)
		{
			nodeQueue.push(temp->right);
			//保存当前节点右孩子的层数:当前层数+1
			levelMap[temp->right] = curLevel + 1;
		}
	}

	return widMax;
}