二叉树层序遍历
一般思路
层序遍历(Level-order Traversal)通常用于遍历树或图的数据结构。对于二叉树,这意味着按照从上到下、从左到右的顺序访问每个节点。以下是解决这类问题时的一般思考过程:
1. 选择数据结构
由于层序遍历需要先访问当前层的所有节点,然后再访问下一层的所有节点,因此队列是一个合适的数据结构。队列能够确保节点以先进先出(FIFO)的方式被处理。
2. 初始化
- 创建一个空的结果数组(通常是一个二维数组)。
- 创建一个队列,并将根节点加入队列。
3. 主循环
进行主循环,直到队列为空:
- 获取当前队列的大小(这就是当前层的节点数量)。
- 创建一个新的数组(或向量),用于存储当前层的节点值。
- 循环处理当前层的每个节点:出队,访问其值,并将其子节点(如果有)加入队列。
- 将当前层的节点值数组添加到结果数组中。
4. 返回结果
返回结果数组。
以上就是解决层序遍历问题时的一般思考过程。这个过程不仅适用于基础的层序遍历,还可以轻微地调整以解决更复杂的问题,如之字形遍历、每层节点的平均值等。
通过一道例题来理解
102.二叉树的层序遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
在这里我们使用迭代的写法
思路 1:初始化数据结构
首先,我们需要一个队列来存储待访问的节点。我们也需要一个二维数组来存储结果。
queue<TreeNode*> q;
vector<vector<int>> result;
思路 2:处理根节点
如果根节点不为空,我们将其加入队列。
if (root != nullptr) {
q.push(root);
}
思路 3:开始主循环
现在我们进入一个循环,该循环将持续到队列为空。在每一次迭代中,我们都会处理当前层的所有节点。
while (!q.empty()) {
// 这里会添加处理当前层节点的代码
}
思路 4:获取当前层的节点数
在主循环的每一次迭代中,首先获取当前层的节点数,这就是队列的当前大小。
int levelSize = q.size();
思路 5:遍历当前层的所有节点
接下来,我们创建一个新的向量 currentLevel,并遍历当前层的所有节点。我们将每个节点从队列中移除,并将其值添加到 currentLevel 向量中。同时,我们将该节点的非空子节点加入队列。
vector<int> currentLevel;
for (int i = 0; i < levelSize; ++i) {
TreeNode* currentNode = q.front();
q.pop();
currentLevel.push_back(currentNode->val);
if (currentNode->left != nullptr) {
q.push(currentNode->left);
}
if (currentNode->right != nullptr) {
q.push(currentNode->right);
}
}
思路 6:保存当前层的结果
最后,我们将 currentLevel 向量添加到 result 二维向量中。
result.push_back(currentLevel);
这样,当主循环结束时,result 二维向量就会包含层序遍历的结果。
将所有这些思路组合在一起,就形成了完整的解决方案。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
// 主函数,用于进行层序遍历并返回结果
vector<vector<int>> levelOrder(TreeNode* root) {
// result 用于存储最终的层序遍历结果
vector<vector<int>> result;
// 如果根节点为空,直接返回空结果
if (root == nullptr) {
return result;
}
// 初始化队列 q,并将根节点加入队列
queue<TreeNode*> q;
q.push(root);
// 主循环,当队列不为空时执行
while (!q.empty()) {
// 获取当前层的节点数量(即队列的大小)
int levelSize = q.size();
// 初始化一个向量,用于存储当前层的节点值
vector<int> currentLevel;
// 遍历当前层的所有节点
for (int i = 0; i < levelSize; ++i) {
// 出队一个节点,并获取其值
TreeNode* currentNode = q.front();
q.pop();
currentLevel.push_back(currentNode->val);
// 如果该节点有左子节点,将其加入队列
if (currentNode->left != nullptr) {
q.push(currentNode->left);
}
// 如果该节点有右子节点,将其加入队列
if (currentNode->right != nullptr) {
q.push(currentNode->right);
}
}
// 将当前层的结果添加到最终结果中
result.push_back(currentLevel);
}
// 返回最终的层序遍历结果
return result;
}
};