层次遍历二叉树,结果分行列出:
[
[3],
[9,20],
[15,7]
]
【思路】
层次遍历要用队列,还要有记录每层节点数的数组。
记录层数是难点,要用每个节点来推算其下一层,看到remlostime的做法是自定义struct,带一个level信息,必须这样吗??
【盲点】
c++栈和队列
头文件:#include<stack> #include<queue>
定义:
定义栈如下:stack<int> stk;
定义队列如下:queue<int> q;
操作:
s.empty() 如果栈为空返回true,否则返回false
s.size() 返回栈中元素的个数
s.pop() 删除栈顶元素但不返回其值
s.top() 返回栈顶的元素,但不删除该元素
s.push() 在栈顶压入新元素
q.empty() 如果队列为空返回true,否则返回false
q.size() 返回队列中元素的个数
q.pop() 删除队列首元素但不返回其值
q.front() 返回队首元素的值,但不删除该元素
q.push() 在队尾压入新元素
q.back() 返回队列尾元素的值,但不删除该元素
【my code】(part,待完善)
private: vector<vector<int> > ret; public: vector<vector<int> > levelOrder(TreeNode *root) { queue<TreeNode*> q; TreeNode *p=root, *r; vector<int> level; int nnum=0; if(p) { q.push(p); level.push_back(1); while(!q.empty()) { level.push_back(0); nnum++; r=q.front(); //cout<<'['<<q.front()<<','; if(r->left){ q.push(r->left); level[nnum]++; } if(r->right){ q.push(r->right); level[nnum]++; } q.pop(); } } }
【评价】
用这个思路比较繁琐,先暂停一下,用个简单的。
【other code】
class Solution { private: vector<vector<int> > ret; public: void solve(int dep, TreeNode *root) { if(root==NULL) return; if(ret.size()>dep) { ret[dep].push_back(root->val); } else{ vector<int> a; a.push_back(root->val); ret.push_back(a); } solve(dep+1, root->left); solve(dep+1, root->right); } vector<vector<int> > levelOrder(TreeNode *root) { ret.clear(); solve(0, root); return ret; } };
【评价】
写的太好了。
if(ret.size()>dep)就是说如果总层数(即ret.size())大于当前所在层数,就在当前层数增加节点值。
不需要用队列和level结构。
这就是所谓的,DFS深度优先遍历。上面我的思路是广度优先,也就是层次遍历的基本思路。
长见识,层次遍历也是可以用深度优先遍历实现的。
记住这个代码!
【后记】
但是效率不高,在这里
【4月23日补充】
看到一个BFS高效简短,不需要在结构中添加level的做法:http://www.cnblogs.com/Azhu/p/4132676.html
【other code2】
vector<vector<int> > levelOrderBottom(TreeNode *root) { vector<vector<int> >ret; if(root==NULL) return ret; vector<int> line; queue<TreeNode *> que; TreeNode * curNode; que.push(root); que.push(NULL); while(que.size()>1){ curNode=que.front(); que.pop(); if(curNode==NULL){ ret.push_back(line); line.clear(); que.push(NULL); continue; } line.push_back(curNode->val); if(curNode->left!=NULL) que.push(curNode->left); if(curNode->right!=NULL) que.push(curNode->right); } ret.push_back(line); //reverse(ret.begin(),ret.end());//这是另一道题的解法 return ret; }
【解析】
这里不需要用level,而是在队列中每一行的最后一个加push(NULL)作为标记,pop时遇到NULL说明一行结束,把前面输出的line push_back到ret后面,
再把line清零。思路十分清晰。记住这段!
用while代替递归,效率要高很多。
【意外收获】
在上面链接中的BFS代码中,有这样一段:
int main() { Solution sol; TreeNode node1(1); TreeNode node2(2); TreeNode node3(3); TreeNode node4(4); node1.right=&node2; node2.left =&node3; node2.right =&node4; vector<vector<int> >ret =sol.levelOrderBottom(&node1); for(int i=0;i<ret.size();i++){ copy(ret[i].begin(),ret[i].end(),ostream_iterator<int>(cout," ")); cout<<endl; } system("pause"); return 0; }
查了一下这句话的用法:
copy(ret[i].begin(),ret[i].end(),ostream_iterator<int>(cout," "));
原来是输入输出的经典句子:
copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec));
//将输入赋给ivec,如果不是int则终结 //下句为将ivec内容输出屏幕 copy(ivec.begin(),ivec.end(),ostream_iterator<int>(cout," "));//以 间隔
需要include<iterator>。
详见:http://blog.csdn.net/fdl19881/article/details/6685744