声明::个人原创代码,转载需附上本文链接
题目::
题目分析::
本题要求实现二叉树的层序遍历,这是一种常见的树遍历方式,其特点是按照从上到下、从左到右的顺序逐层访问二叉树的所有节点。与普通的前序、中序、后序遍历不同,层序遍历需要将每一层的节点值存储在一个一维数组中,并将所有层的数组组合成一个二维数组作为输出。
层序遍历的关键在于如何有效地逐层访问节点。由于树的层级结构,我们不能简单地使用递归或迭代的方法来实现。相反,我们需要一种能够同时处理当前层和下一层节点的方法。队列(Queue)是一种非常适合这种需求的数据结构,因为它可以按照先进先出(FIFO)的原则存储和访问元素。
思路分析::
使用队列实现层序遍历
层序遍历的核心思想是使用队列来存储每一层的节点。通过逐层访问节点,可以保证按照从上到下、从左到右的顺序访问所有节点
双队列法
为了实现层序遍历,可以使用两个队列交替存储当前层和下一层的节点。这样可以避免在访问当前层时修改队列,从而简化代码逻辑。具体步骤如下:
-
初始化两个空队列,
one
用于存储当前层的节点,two
用于存储下一层的节点。 -
将根节点加入
one
队列。 -
当
one
队列不为空时,执行以下操作:-
从
one
队列中取出所有节点,访问它们的值,并将下一层的节点加入到two
队列中。 -
将
one
队列中的节点值存储在一个一维数组中,并将该数组添加到结果二维数组中。 -
交换
one
和two
队列,以便下一次循环时处理下一层节点。
-
逐层访问
从根节点开始,逐层访问节点,并将每一层的节点值存储在一个一维数组中。每访问完一层,将下一层的节点加入队列,直到所有层都被访问完毕。
代码分析
-
TreeNode结构体:定义了二叉树节点的结构体,包含节点值和左右子节点指针。
-
GetOneLevel函数:从当前层的队列中取出所有节点,访问它们的值,并将下一层的节点加入到下一层的队列中。返回当前层的节点值数组。这个函数通过一个
while
循环遍历当前层的所有节点,对于每个节点,取出其值并添加到结果数组中,然后检查是否有左右子节点,如果有则将它们加入到下一层的队列中。 -
levelOrder函数:使用两个队列交替存储当前层和下一层的节点,逐层访问二叉树的节点,并将每一层的节点值存储在一个一维数组中,最终返回一个二维数组。这个函数首先检查根节点是否为空,如果为空则直接返回空数组。然后初始化两个队列和一个结果数组。使用一个
while
循环来遍历所有层,每次循环中,通过调用GetOneLevel
函数处理一层节点,并将结果添加到结果数组中。循环结束后,返回结果数组。
详细代码::
/**
* 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) {}
* };
*/
#include<queue>
class Solution {
public:
//读取二叉树单层数据
//AccessNodes存储当前正在访问的二叉树层所有节点
//StorageNodes记录当前访问的二叉树层下一层所有节点
vector<int> GetOneLevel(queue<TreeNode*>& AccessNodes,queue<TreeNode*>& StorageNodes){
vector<int> OneLevel;
TreeNode* temp;
while(!AccessNodes.empty()){
temp = AccessNodes.front();
AccessNodes.pop();
OneLevel.push_back(temp->val);
//是否有左右子树
if(temp->left!=nullptr) StorageNodes.push(temp->left);
if(temp->right!=nullptr) StorageNodes.push(temp->right);
}
//使用move语义加快返回速率
return std::move(OneLevel);
}
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> one,two;
vector<vector<int> > ans;
if(root==nullptr) return ans;
//记录当前要访问的树层节点位于哪一个队列
int flag = 1;
one.push(root);
while(1){
if(flag == 1){
//插入一层数据
ans.push_back(GetOneLevel(one,two));
flag = 0;
if(two.empty()) break; //无下一层跳出循环
}
else{
//插入一层数据
ans.push_back(GetOneLevel(two,one));
flag=1;
if(one.empty()) break; //无下一层跳出循环
}
}
return ans;
}
};