一、二叉树的宽度优先遍历
二叉树的宽度优先遍历,又叫广度优先遍历、层序优先遍历。
二叉树的宽度优先遍历可以使用队列完成。
算法步骤:
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;
}