题目描述:(来源于力扣 剑指offer32)
这道题和前面的两题比较类似,
1)层序遍历
2)分行从上到下打印二叉树
这道题,
3)之字形打印二叉树
需要考虑3点:
- 层序遍历二叉树
- 分层打印
- 之字形(奇数层和偶数层顺序不同)
层序遍历二叉树可以考虑使用队列
存储节点的值;
分层打印可以考虑计算队列
中元素的个数来换行;
之字形打印,奇数层正序,偶数层逆序,通过层数的奇偶性来判断。
下面使用两种方式来实现:层序遍历+双栈
or 层序遍历+队列+deque
。
1)层序遍历+双栈
如果只是层序遍历二叉树,那么使用队列
就可以满足要求。但是这里有正序、逆序的要求,所以队列不如栈比较方便。
使用两个栈,思路很简单,将其分为奇数层栈
和偶数层栈
。
只需要判断层的奇偶性,将子节点数据压入对应的栈,即可。需要注意的是由于正序和逆序的区别,不同栈左右子节点压入的顺序不同。
具体实现:
class Solution {
private:
int level=1;
vector<int> stackLevel(stack<TreeNode*> &s, stack<TreeNode*> &sS, bool flag){
//第一个参数是主栈,当前节点
//第二个参数是存储子节点
//flag:奇偶性,因为需要根据奇偶性判断子节点的压入顺序
vector<int> res1;
int sSize=s.size();//主栈的元素个数,用于分层打印
for(int i=0; i<sSize; ++i){
TreeNode* cur=s.top();
res1.push_back(cur->val);
s.pop();
if(flag){//子节点压入
if(cur->left!=nullptr)
sS.push(cur->left);
if(cur->right!= nullptr)
sS.push(cur->right);
}else{
if(cur->right!= nullptr)
sS.push(cur->right);
if(cur->left!=nullptr)
sS.push(cur->left);
}
}
level++;//层数控制
return res1;
}
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res2;
if(root==nullptr)
return res2;
stack<TreeNode*> s1; //奇层
stack<TreeNode*> s2; //偶层
s1.push(root);
while (!s1.empty() || !s2.empty()){ //只有当两个栈都为空时,才表示结束
if(level % 2 != 0) //层数的奇偶性判断
res2.push_back(stackLevel(s1,s2,true));
else
res2.push_back(stackLevel(s2,s1,false));
}
return res2;
}
};
2)层序遍历+队列+deque
使用双栈存储,实现之字形打印的思路比较简洁,分开存储奇偶即可。
那如果不分开存储,应该使用哪种数据结构来存储,才能实现奇偶的不同遍历?
答案是deque
。
deque是一个可以双端插入和删除的队列,我们可以使用这个特性:
1)奇数层——正序打印,在deque的尾端依次插入;
2)偶数层——逆序打印,在deque的首端依次插入。
我这里使用了队列+deque
,其实完全可以使用双deque
。但是分析过程,就可以发现,用于层序遍历的存储使用队列就可以满足要求。
请注意:这里和前面的双栈不同——
前面的双栈都是用来存放当前节点或者子节点的,最后的输出是使用一维vector来存储每一层的遍历结果,使用二维vector来存储最终结果;
而这里的队列是用来存储节点的,deque是用来存储每一层的遍历结果,最后使用二维vector来存储输出结果。(因此,最后需要将deque的元素转换成一维vector)。
算法流程:
1)使用队列存储当前节点和子节点;
2)使用deque来存放每一层的遍历结果。
具体实现:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res2;
if(root== nullptr)
return res2;
int level=1;
queue<TreeNode*> q;
deque<int> dq;
q.push(root);
while (!q.empty()){
int qsize=q.size();
dq.clear();
for(int i=0;i<qsize;++i){
TreeNode* cur=q.front();
//根据奇偶性决定每一层遍历结果的顺序
level%2!=0 ? dq.push_back(cur->val) : dq.push_front(cur->val);
q.pop();
if(cur->left!= nullptr)
q.push(cur->left);
if(cur->right!=nullptr)
q.push(cur->right);
}
level++;
vector<int> res1(dq.begin(),dq.end());
res2.push_back(res1);
}
return res2;
}
};