【问题描述】
对【二叉树1】中建立的二叉树逐层打印,也就是说第一行打印第0层根节点,第二行打印第一层……如此类推。
【举例】
一棵二叉树如下:
打印结果为:
【代码】
编程之美介绍了两种实现,一种是递归,该方法需要一个层数作为参数。
另一种就是如下方法,用两个游标记录树的每一层。
代码仅为该函数的实现,和所需头文件。并且不包含二叉树节点的定义以及main函数的调用
#include <iostream>
#include <vector>
using namespace std;
void PrintBTreeByLevel(BTreeNode *root){
if(root==NULL)
return;
vector<BTreeNode*> vec;
vec.push_back(root);
int current=0,last=1;
while(current<vec.size())
{
while(current<last)
{
cout<<vec[current]->value<<" ";
if(vec[current]->leftchild)//A
vec.push_back(vec[current]->leftchild);
if(vec[current]->rightchild)//B
vec.push_back(vec[current]->rightchild);
++current;
}
last=vec.size();
cout<<endl;
}
}
做leetcode的时候发现上述代码超出内存限制,主要原因在vector中存放了所有的节点,最好选取queue来存放节点,每次只存放一层。还有leetcode函数输出为一个二维的vector,不是单纯打印,所以稍稍复杂。
有三种思路:
【思路一】用一个NULL做分隔
vector<vector<int> > levelOrder(TreeNode *root) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<vector<int>> levels;
queue<TreeNode *> que;
if (!root)
return levels;
que.push(root);
que.push(NULL);
while(que.front() != NULL) {
vector<int> line;
TreeNode *temp = que.front();
que.pop();
while (temp != NULL) {
line.push_back(temp->val);
if (temp->left)
que.push(temp->left);
if (temp->right)
que.push(temp->right);
temp = que.front();
que.pop();
}
levels.push_back(line);
que.push(NULL);
}
return levels;
}
【思路二】申请一个附加容器,存储当前层的下一层,然后将下一层再拷贝回queue
vector<vector<int> > levelOrder(TreeNode *root) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<vector<int>> levels;
queue<TreeNode *> q;
if (!root)
return levels;
q.push(root);
while(!q.empty()) {
vector<int> l;
vector<TreeNode *> temp;
while(!q.empty()) {
TreeNode *p = q.front();
q.pop();
l.push_back(p->val);
if (p->left) temp.push_back(p->left);
if (p->right) temp.push_back(p->right);
}
levels.push_back(l);
for (int i=0; i<temp.size(); i++)
q.push(temp[i]);
}
return levels;
}
【思路三】递归的方法,函数travers是一个top-buttom的方法,算法很简单很奇妙,是leetcode上的大牛写的。简单理解一下:
if (level > result.size())
判断result中是否出现过这一层的元素。root='a'时,level=1,result.size()=0,说明遍历到第一层时,result还是空的,所以需要需要push进去一个vector<int>;root=’b'时,level=2,result.size()=1,继续push;root='c'时,level=2,result.size()=2,直接执行后面的语句。
result[level-1].push_back(root->val)
因为result是从0开始的,level是从1开始的,所以需要result[level-1]进行push
vector<vector<int> > levelOrderBottom(TreeNode *root) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<vector<int>> result;
traverse(root, 1, result);
std::reverse(result.begin(), result.end());
return result;
}
void traverse(TreeNode *root, int level, vector<vector<int>> &result) {
if (!root)
return;
if (level > result.size()) {
vector<int> temp;
result.push_back(temp);
}
result[level-1].push_back(root->val);
traverse(root->left, level+1, result);
traverse(root->right, level+1, result);
}
【扩展一】打印一棵二叉树的镜像
只需要交换上述代码中A和B的两段if,也就是先让一个节点的右孩子入栈,再让左孩子入栈,结果如下:
【扩展二】从下到上逐层打印二叉树
可以在正向遍历的结果后加上一句std::reverse(result.begin(),result.end())做反转