1.二叉树的层序遍历
方法一:广度优先搜索
// 定义一个名为Solution的类
class Solution {
public:
// 定义一个公共方法levelOrder,接受一个二叉树的根节点指针作为参数,返回一个二维向量
vector> levelOrder(TreeNode* root) {
// 初始化一个空的二维向量ret,用于存储层序遍历的结果
vector> ret;
// 如果根节点为空,直接返回空的二维向量
if (!root) {
return ret;
}
// 创建一个队列q,用于层序遍历中的广度优先搜索
queue<TreeNode*> q;
// 将根节点推入队列
q.push(root);
// 当队列不为空时,循环进行层序遍历
while (!q.empty()) {
// 获取当前层的节点数量(即队列的大小)
int currentLevelSize = q.size();
// 在ret中添加一个新的空向量,用于存储当前层的节点值
ret.push_back(vector<int>());
// 循环处理当前层的每个节点
for (int i = 1; i <= currentLevelSize; ++i) {
// 取出队列的前端节点,并将其从队列中移除
auto node = q.front();
q.pop();
// 将当前节点的值添加到ret的当前层向量中
ret.back().push_back(node->val);
// 如果当前节点有左子节点,则将左子节点推入队列
if (node->left) q.push(node->left);
// 如果当前节点有右子节点,则将右子节点推入队列
if (node->right) q.push(node->right);
}
}
// 返回层序遍历的结果
return ret;
}
};
核心问题:
在层序遍历的过程中,我们使用队列q来按照广度优先的顺序存储和访问二叉树的节点。当我们调用q.front()来获取队列前面的节点时,这个节点属于当前层级的节点,而不是下一层级的节点。但是,当我们把这个节点从队列中移除(通过q.pop())并处理它的子节点时,我们会把这些子节点(如果存在的话)压入队列中。
现在,让我们解释一下为什么在处理完当前层级的节点后,q.size()表示的是下一层级的节点数量。
当我们开始处理当前层级的节点时,队列中存储的是下一层级的节点。因此,q.size()在开始处理当前层级时表示的是下一层级的节点数量。
当我们处理当前层级的节点时,我们会把这些节点从队列中移除,并处理它们的子节点。如果我们把当前层级的所有节点都处理完了,那么队列中剩下的就是下一层级的节点。 因此,在处理完当前层级的所有节点后,q.size()表示的是下一层级的节点数量。这是因为我们已经把当前层级的所有节点从队列中移除了,而它们的子节点(即下一层级的节点)被压入了队列中。
总的来说,q.size()之所以在处理完当前层级后表示下一层级的节点数量,是因为我们使用队列来进行广度优先搜索,按照层级顺序处理节点,并在处理完当前层级的节点后将其从队列中移除,并将下一层级的节点压入队列中。因此,q.size()反映的是队列中剩余节点的数量,也就是下一层级的节点数量。
2.二叉树的锯齿形层序遍历
方法一:广度优先遍历
// 定义一个Solution类,用于存储二叉树的锯齿形层次遍历解决方案
class Solution {
public:
// 定义一个二维向量,用于存储每一层的节点值
vector> zigzagLevelOrder(TreeNode* root) {
// 初始化结果向量
vector> ans;
// 如果根节点为空,则直接返回空的结果向量
if (!root) {
return ans;
}
// 创建一个队列,用于存储待处理的节点
queue<TreeNode*> nodeQueue;
// 将根节点加入队列
nodeQueue.push(root);
// 定义一个布尔变量,用于决定遍历顺序,初始值为true,表示从左到右
bool isOrderLeft = true;
// 当队列不为空时,继续处理
while (!nodeQueue.empty()) {
// 创建一个双端队列,用于存储当前层的节点值
deque<int> levelList;
// 获取当前层的节点数量
int size = nodeQueue.size();
// 遍历当前层的所有节点
for (int i = 0; i < size; ++i) {
// 获取队列前面的节点
auto node = nodeQueue.front();
// 将节点从队列中移除
nodeQueue.pop();
// 如果isOrderLeft为true,则从左到右添加节点值到levelList中
if (isOrderLeft) {
levelList.push_back(node->val);
} else {
// 否则,从右到左添加节点值到levelList中
levelList.push_front(node->val);
}
// 如果当前节点有左子节点,则将其加入队列中,以便下一层处理
if (node->left) {
nodeQueue.push(node->left);
}
// 如果当前节点有右子节点,则将其加入队列中,以便下一层处理
if (node->right) {
nodeQueue.push(node->right);
}
}
// 将当前层的levelList添加到结果向量ans中
ans.emplace_back(vector<int>{levelList.begin(), levelList.end()});
// 切换isOrderLeft的值,以便下一层使用相反的遍历顺序
isOrderLeft = !isOrderLeft;
}
// 返回结果向量ans
return ans;
}
};