我们可以先用queue先进先出的特性。
往queue里插入一个节点,然后弹出这个节点,用vector去接受这个节点。
然后再往queue里插入另一个节点,再弹出,vector再接受,循环往复。
直到vector里面已经存了整个树的节点为止。
但是这样的话vector打印出来就是整个样子:
但是我们想要的是这个样子:
也就是我们的vector应该按树层来存储节点
我们再创建一个二维vector,vector<vector>vv;
让vector每次存储每一树层的节点,如 (图c).
然后vector反馈给二维数组vv,这样vv就可以达到 (图b)的效果。
另外,如何保证刚好让vector每次都可以存储一层的节点呢。
可以用一个变量 levesize来统计下一层节点个数,v只要push_back levesize个节点就刚好够一层。
然后再给vv。
我写了这样的代码:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> q;
vector<int> v;
vector<vector<int>> vv;
//if(root==NULL)return NULL;
if(root) q.push(root);
int levesize=1;
while(!q.empty())
{
while(levesize--)
{
TreeNode* Front=q.front();
q.pop();
v.push_back(Front->val);
if(root->right)q.push(Front->left);
if(root->right)q.push(Front->right);
}
levesize=q.size();
vv.push_back(v);
}
return vv;
}
};
然后有一个报错:
这是因为我们应该去判断队列的下一层的左右子树是否为空,而不是去判断TreeNode:
因root在刚开始就判断过
if(root==NULL)return vv;
但是仍然有逻辑错误 :
可以明显地看出来是因为我们的 v没有清空导致的。
两种解决办法,一种是显示写v.pop_back() ,但是要自己控制弹出,如下就是仍然有报错的:
第二种方法就是我们隐式的方法,我们把vectorv放到while循环内部定义,这样出了作用域
v 就会销毁。
整体代码如下:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> q;//套用树模版来个队列
vector<vector<int>> vv;//最后把遍历完的数据放到vv里
int levesize=0;
if(root) q.push(root);
levesize=1;
while(!q.empty())//当队列不为空时
{ vector<int> v;
while(levesize--)
{
TreeNode* Front=q.front();
q.pop();
v.push_back(Front->val);
if(Front->left) q.push(Front->left);
if(Front->right) q.push(Front->right);
}
levesize=q.size();
vv.push_back(v);
}
return vv;
}
};