训练题:序列化二叉树

题目:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/

  1. // 宽度优先遍历
  2. string serialize( TreeNode* root )
  3. {
  4. if( !root ) { return ""; }
  5. queue<TreeNode*> q;
  6. TreeNode* tmpNode = nullptr;
  7. string ret;
  8. for( q.push( root ); !q.empty(); q.pop() )
  9. {
  10. tmpNode = q.front();
  11. if( tmpNode )
  12. {
  13. ret.append( to_string( tmpNode->val ) );
  14. q.push( tmpNode->left );
  15. q.push( tmpNode->right );
  16. }
  17. ret.append( "," );
  18. }
  19. return ret;
  20. }
  21. // Decodes your encoded data to tree.
  22. TreeNode* deserialize( string data )
  23. {
  24. if( data.empty() ) { return nullptr; }
  25. const auto size = data.size();
  26. queue<TreeNode*> q;
  27. stringstream ss;
  28. TreeNode* tmpNewNode = nullptr;
  29. TreeNode* tmpNode = nullptr;
  30. TreeNode* root = nullptr;
  31. bool start = true;
  32. bool tmpSuccess = false;
  33. bool tmpLeft = true;
  34. int tmpVal;
  35. for( int startIdx = 0, endIdx = startIdx; endIdx != size; ++endIdx )
  36. {
  37. if( data[endIdx] == ',' )
  38. {
  39. tmpSuccess = parseVal( data, ss, startIdx, endIdx, tmpVal );
  40. if( tmpSuccess ) { tmpNewNode = new TreeNode( tmpVal ); }
  41. else { tmpNewNode = nullptr; }
  42. if( start )
  43. {
  44. if( !tmpNewNode ) { return nullptr; }
  45. root = tmpNewNode;
  46. q.push( tmpNewNode );
  47. tmpLeft = true;
  48. start = false;
  49. }
  50. else
  51. {
  52. tmpNode = q.front();
  53. if( tmpLeft ) { tmpNode->left = tmpNewNode; }
  54. else
  55. {
  56. tmpNode->right = tmpNewNode;
  57. q.pop();
  58. }
  59. if( tmpNewNode ) { q.push( tmpNewNode ); }
  60. tmpLeft = !tmpLeft;
  61. }
  62. startIdx = endIdx + 1;
  63. }
  64. }
  65. return root;
  66. }
  67. bool parseVal( const string &data, stringstream &ss, const int &start, const int &end, int &val )
  68. {
  69. if( end <= start ) { return false; }
  70. ss << data.substr( start, end - start );
  71. ss >> val;
  72. ss.clear();
  73. return true;
  74. }

训练题:二叉树后续遍历序列

题目:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/

方法一:递归(模拟法)

  • 时间复杂度:O(n2)
  • 空间复杂度:O(n)
  1. bool verifyPostorder( vector<int> &postorder )
  2. {
  3. if( postorder.size() > 1000 ) { return false; }
  4. return traverse( postorder, 0, static_cast<short>( postorder.size() - 1 ) );
  5. }
  6. bool traverse( vector<int> &postorder, short start, short end )
  7. {
  8. if( end <= start ) { return true; }
  9. // 左子树区间:[start, leftEnd)
  10. short leftEnd = start;
  11. for( ; leftEnd < end && postorder[leftEnd] < postorder[end]; ++leftEnd );
  12. // 存在左子树区间,则递归遍历。
  13. if(leftEnd != start && !traverse( postorder, start, leftEnd-1 )) return false;
  14. if(leftEnd != end){
  15. // 右子树区间:[leftEnd, rightEnd)
  16. short rightEnd = leftEnd;
  17. for( ; rightEnd < end && postorder[rightEnd] > postorder[end]; ++rightEnd);
  18. // 如果是二叉搜索树,则右子树区间应该是[leftEnd, end),即rightEnd = end。
  19. if(rightEnd != end) return false;
  20. // 递归遍历右子树区间
  21. if( !traverse( postorder, leftEnd, rightEnd-1 ) ) { return false; }
  22. }
  23. return true;
  24. }

方法二:栈

  • 时间复杂度:O(n)
  • 空间复杂度:O(n) ```cpp

bool verifyPostorder( vector &postorder ) { if( postorder.size() > 1000 ) { return false; }

  1. stack<int> stk;
  2. int root = INT_MAX;
  3. for(auto it = postorder.rbegin(); it != postorder.rend(); ++it){
  4. if(root < *it) return false;
  5. for(; !stk.empty() && *it < stk.top(); stk.pop()) root = stk.top();
  6. stk.push(*it);
  7. }
  8. return true;

}

  1. <a name="JxWmC"></a>
  2. # 训练题:二叉树查找路径
  3. 题目:[http://t.cn/A6qUHzz3](http://t.cn/A6qUHzz3)
  4. <a name="M0UNJ"></a>
  5. ## 方法:递归
  6. ```cpp
  7. vector<vector<int>> pathSum(TreeNode* root, int target) {
  8. if(!root) return {};
  9. vector<vector<int>> data;
  10. vector<int> path;
  11. int sum = target;
  12. traverse(root, data, path, sum);
  13. return data;
  14. }
  15. void traverse(TreeNode* root,vector<vector<int>> &data, vector<int>& path, int &sum){
  16. if(!root) return;
  17. path.push_back(root->val);
  18. sum -= root->val;
  19. if(!root->left && !root->right && !sum) data.push_back(path);
  20. else
  21. {
  22. traverse(root->left, data, path, sum);
  23. traverse(root->right, data, path, sum);
  24. }
  25. sum += root->val;
  26. path.pop_back();
  27. }

训练题:二叉搜索树转链表

题目:http://t.cn/A6q5lHBc

递归方法一

  1. Node* treeToDoublyList(Node* root) {
  2. if(!root) return root;
  3. Node head, *tail = &head;
  4. // 中序遍历root,转化成双向链表,并返回链表表尾
  5. tail = traverse(root, tail);
  6. // 表尾与表头接上。
  7. tail->right = head.right;
  8. head.right->left = tail;
  9. return head.right;
  10. }
  11. Node* traverse(Node* root, Node* tail){
  12. if(!root) return tail;
  13. tail = traverse(root->left, tail);
  14. tail->right = root;
  15. root->left = tail;
  16. tail = root;
  17. return traverse(root->right, tail);
  18. }

递归方法二

  1. class Solution {
  2. public:
  3. Node* treeToDoublyList(Node* root) {
  4. if(!root) return root;
  5. traverse(root);
  6. head->left = tail;
  7. tail->right = head;
  8. return head;
  9. }
  10. private:
  11. Node* head, *tail;
  12. void traverse(Node* root){
  13. if(!root) return;
  14. traverse(root->left);
  15. if(!head) head = tail = root;
  16. else tail->right = root;
  17. root->left = tail;
  18. tail = root;
  19. traverse(root->right);
  20. }
  21. };

训练题:判断二叉树平衡

题目:http://t.cn/A6qYF1Mg

方法一:递归一

  1. bool isBalanced(TreeNode* root) {
  2. if(!root) return true;
  3. return abs(depth(root->left) - depth(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right);
  4. }
  5. // 递归求root的深度
  6. int depth(TreeNode* root){
  7. if(!root) return 0;
  8. return max(depth(root->left), depth(root->right)) + 1;
  9. }

方法二:递归二

  1. bool isBalanced(TreeNode* root) {
  2. return traverse(root) != -1;
  3. }
  4. int traverse(TreeNode* root)
  5. {
  6. if(!root) return 0;
  7. int left = traverse(root->left);
  8. if(left == -1) return -1;
  9. int right = traverse(root->right);
  10. if(right == -1) return -1;
  11. return abs(left - right) < 2 ? max(left, right) + 1 : -1;
  12. }

训练题:最近公共祖先(LCA)

场景一:二叉搜索树

递归法

  1. // 递归方法一:实测结果,这个更快一点
  2. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  3. if(!root || root == p || root == q) return root;
  4. if((root->val - p->val)*(root->val - q->val) < 0) return root;
  5. if(root->val > p->val && root->val > q->val) return lowestCommonAncestor(root->left, p, q);
  6. else return lowestCommonAncestor(root->right, p, q);
  7. }
  8. // 递归方法二:
  9. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  10. if(!root || root == p || root == q) return root;
  11. if(max(p->val, q->val) < root->val) return lowestCommonAncestor(root->left, p, q);
  12. if(min(p->val, q->val) > root->val) return lowestCommonAncestor(root->right, p, q);
  13. return root;
  14. }

迭代法

  1. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  2. while(true)
  3. {
  4. if( min(p->val, q->val) > root->val ) root = root->right;
  5. else if( max(p->val, q->val) < root->val ) root = root->left;
  6. else break;
  7. }
  8. return root;
  9. }

场景二:普通二叉树

题目:http://t.cn/A65Tm8ou

方法一:递归

  1. // 由于递归的深度优先特性(从下往上遍历),找到的一个公共祖先其实就是深度最大的祖先,即最近公共祖先。
  2. // root为遍历的当前根节点,p、q为其下的节点。
  3. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  4. // 优先遍历到了p或者q节点、或者到叶节点都没有遍历到。
  5. if(!root || root == p || root == q) return root;
  6. // 分别遍历了一遍左右子树,分别得到了left/right节点
  7. TreeNode* left = lowestCommonAncestor(root->left, p, q);
  8. TreeNode* right = lowestCommonAncestor(root->right, p, q);
  9. // 如果left为空,而right不为空,则表示p是q的子节点,或者反之,只有这样才会导致遍历到p或者q就停止了。
  10. // right为空,left不为空同理。
  11. //
  12. // 如果left不为空且right不为空,则表示p、q分别在左右子树中,因此公共祖先应该是root。
  13. return !left ? right : (!right ? left : root);
  14. }

方法二:哈希表

用哈希表记录每个节点的父节点。问题就变成了查找两个链表的第一个公共节点。
见:https://www.yuque.com/tvvhealth/cs/pn55xq

  1. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
  2. map<TreeNode*, TreeNode*> info;
  3. recordParent(root, info);
  4. TreeNode* nodep = p, *nodeq = q;
  5. while(nodep != nodeq){
  6. nodep = nodep == root ? q : info[nodep];
  7. nodeq = nodeq == root ? p : info[nodeq];
  8. }
  9. return nodep;
  10. }
  11. void recordParent(TreeNode* root, map<TreeNode*, TreeNode*>& info){
  12. if(!root) return;
  13. if(root->left) info[root->left] = root;
  14. if(root->right) info[root->right] = root;
  15. recordParent(root->left, info);
  16. recordParent(root->right, info);
  17. }

训练题:二叉搜索树K大数

题目:http://t.cn/A6qjYlXa

方法一:递归

  1. int kthLargest(TreeNode* root, int k) {
  2. int val;
  3. traverse(root, val, k);
  4. return val;
  5. }
  6. void traverse(TreeNode* root, int&val, int &k){
  7. if(!k || !root) return;
  8. traverse(root->right, val, k);
  9. if(!(--k)){
  10. val = root->val;
  11. return;
  12. }
  13. traverse(root->left, val, k);
  14. }

方法二:迭代

  1. int kthLargest(TreeNode* root, int k) {
  2. stack<TreeNode*> stk;
  3. stk.push(root);
  4. while(!stk.empty()){
  5. root = stk.top();
  6. stk.pop();
  7. if(!root->right && !--k){
  8. return root->val;
  9. }
  10. if(root->left) stk.push(root->left);
  11. stk.push(root);
  12. if(root->right) stk.push(root->right);
  13. }
  14. return -1;
  15. }

训练题:二叉树深度

题目:http://t.cn/A6qjTSIv

方法一:递归

  1. int maxDepth(TreeNode* root) {
  2. if(!root) return 0;
  3. return max(maxDepth(root->left), maxDepth(root->right)) + 1;
  4. }

方法二:迭代

广度优先算法。

  1. int maxDepth(TreeNode* root) {
  2. int depth = 0;
  3. queue<TreeNode*> q1, q2;
  4. TreeNode* node;
  5. if(root) q1.push(root);
  6. while(!q1.empty() || !q2.empty()){
  7. if(!q1.empty()){
  8. ++depth;
  9. while(!q1.empty()){
  10. node = q1.front();
  11. q1.pop();
  12. if(node->left) q2.push(node->left);
  13. if(node->right) q2.push(node->right);
  14. }
  15. }
  16. if(!q2.empty()){
  17. ++depth;
  18. while(!q2.empty()){
  19. node = q2.front();
  20. q2.pop();
  21. if(node->left) q1.push(node->left);
  22. if(node->right) q1.push(node->right);
  23. }
  24. }
  25. }
  26. return depth;
  27. }

训练题:重建二叉树

题目:http://t.cn/A6z20HLo

方法一:递归

  • 时间复杂度:O(n)
  • 空间复杂度:O(n) ```cpp

TreeNode* buildTree( vector &preorder, vector &inorder ) { if( preorder.empty() || preorder.size() != inorder.size() ) { return nullptr; }

  1. const auto size_pre = preorder.size();
  2. const auto size_in = inorder.size();
  3. map<int, int> inMap;
  4. for( int i = 0; i < size_in; ++i ) { inMap[inorder[i]] = i; }
  5. return _build( preorder, inorder, inMap, 0, size_pre - 1, 0, size_in - 1 );

}

TreeNode* _build( const vector &preorder, const vector &inorder, map &inMap, const int &preStart, const int &preEnd, const int &inStart, const int &inEnd ) { if( preStart > preEnd ) { return nullptr; }

  1. TreeNode* root = new TreeNode( preorder[preStart] );
  2. if( preStart == preEnd ) { return root; }
  3. // 当前根节点在中序遍历中的索引。
  4. int rootIdx_in = inMap[preorder[preStart]];
  5. root->left = _build( preorder, inorder, inMap, preStart + 1, preStart + rootIdx_in - inStart, inStart, rootIdx_in - 1 );
  6. root->right = _build( preorder, inorder, inMap, preStart + rootIdx_in - inStart + 1, preEnd, rootIdx_in + 1, inEnd );
  7. return root;

}

  1. <a name="QQ8hK"></a>
  2. ## 方法二:迭代(待完成)
  3. ```cpp

训练题:树的子结构

题目:http://t.cn/A6GgETFz

方法一:双递归

递归一:遍历目标子树
递归二:在递归一的每个子过程中,再递归检测当前递归节点为根节点的目标子树。

  • 时间复杂度:O(AB)
  • 空间复杂度:O(A) ```cpp

// 递归1 bool isSubStructure( TreeNode A, TreeNode B ) { if( !A || !B ) { return false; } return fuck( A, B ) || isSubStructure( A->left, B ) || isSubStructure( A->right, B ); }

// 递归2 bool fuck( TreeNode A, TreeNode B ) { return !B || A && A->val == B->val && fuck( A->left, B->left ) && fuck( A->right, B->right ); }

  1. <a name="d3WYD"></a>
  2. # 训练题:树的镜像
  3. 题目:[http://t.cn/A6GgnP1E](http://t.cn/A6GgnP1E)
  4. <a name="e5KM1"></a>
  5. ## 方法一:递归
  6. - 时间复杂度:O(n)
  7. - 空间复杂度:O(n)
  8. ```cpp
  9. TreeNode* mirrorTree(TreeNode* root) {
  10. if(!root) return root;
  11. TreeNode* tmpNode = nullptr;
  12. tmpNode = root->left;
  13. root->left = mirrorTree(root->right);
  14. root->right = mirrorTree(tmpNode);
  15. return root;
  16. }

方法二:迭代(辅助栈/队列)

  1. TreeNode* mirrorTree(TreeNode* root) {
  2. if(!root) return root;
  3. queue<TreeNode*> q; // 可以用栈/队列
  4. q.push(root);
  5. for(TreeNode* node, *tmpNode; !q.empty();){
  6. node = q.front();
  7. q.pop()
  8. tmpNode = node->left;
  9. node->left = node->right;
  10. node->right = tmpNode;
  11. if(node->left) q.push(node->left);
  12. if(node->right) q.push(node->right);
  13. }
  14. return root;
  15. }

训练题:对称二叉树

题目:http://t.cn/A6GgnWmH

方法一:递归

  1. bool isSymmetric(TreeNode* root) {
  2. if(!root) return true;
  3. return fuck(root->left, root->right);
  4. }
  5. bool fuck(TreeNode* left, TreeNode* right){
  6. if(!left && !right) return true;
  7. if(!left || !right || left->val != right->val) return false;
  8. return fuck(left->left, right->right) && fuck(left->right, right->left);
  9. }

方法二:迭代

既然可以递归,那就可以考虑迭代。
如果是对称的,则中-左-右和中-右-左遍历的每一步都是对称的。可以用队列或者栈。

  1. bool isSymmetric(TreeNode* root) {
  2. if(!root || !root->left && !root->right) return true;
  3. if(!root->left || !root->left) return false;
  4. queue<TreeNode*> q1, q2;
  5. q1.push(root);
  6. q2.push(root);
  7. for(TreeNode* tmpNode1, *tmpNode2; !q1.empty() && !q2.empty();) {
  8. tmpNode1 = q1.front();
  9. tmpNode2 = q2.front();
  10. q1.pop();
  11. q2.pop();
  12. if(!tmpNode1 && !tmpNode2){}
  13. else if(tmpNode1 && tmpNode2 && tmpNode1->val == tmpNode2->val){}
  14. else return false;
  15. if(tmpNode1){
  16. q1.push(tmpNode1->left);
  17. q1.push(tmpNode1->right);
  18. q2.push(tmpNode2->right);
  19. q2.push(tmpNode2->left);
  20. }
  21. }
  22. return true;
  23. }

方法三:迭代(改进)

可以将两个队列合并,将两个遍历的过程每一步都是先后放即可。

  1. bool isSymmetric(TreeNode* root) {
  2. if(!root || !root->left && !root->right) return true;
  3. if(!root->left || !root->left) return false;
  4. queue<TreeNode*> q;
  5. q.push(root);
  6. q.push(root);
  7. for(TreeNode* tmpNode1, *tmpNode2; !q.empty();) {
  8. tmpNode1 = q.front();
  9. q.pop();
  10. tmpNode2 = q.front();
  11. q.pop();
  12. if(!tmpNode1 && !tmpNode2){}
  13. else if(tmpNode1 && tmpNode2 && tmpNode1->val == tmpNode2->val){}
  14. else return false;
  15. if(tmpNode1){
  16. q.push(tmpNode1->left);
  17. q.push(tmpNode2->right);
  18. q.push(tmpNode1->right);
  19. q.push(tmpNode2->left);
  20. }
  21. }
  22. return true;
  23. }

训练题:二叉树遍历

场景一:递归遍历(前、中、后)

题目:http://t.cn/A6VhuQIl

  1. /**
  2. * struct TreeNode {
  3. * int val;
  4. * struct TreeNode *left;
  5. * struct TreeNode *right;
  6. * };
  7. */
  8. // 前序遍历
  9. void preOrder( TreeNode* root )
  10. {
  11. if( !root ) { return; }
  12. printf("%d", root->val);
  13. preOrder( root->left, container );
  14. preOrder( root->right, container );
  15. }
  16. // 中序遍历
  17. void midOrder( TreeNode* root, vector<int> &container )
  18. {
  19. if( !root ) { return; }
  20. midOrder( root->left, container );
  21. printf("%d", root->val);
  22. midOrder( root->right, container );
  23. }
  24. // 后序遍历
  25. void postOrder( TreeNode* root, vector<int> &container )
  26. {
  27. if( !root ) { return; }
  28. postOrder( root->left, container );
  29. postOrder( root->right, container );
  30. printf("%d", root->val);
  31. }

场景二:层序遍历

自顶向下

题目:http://t.cn/A6A1oc4c
用队列结构。

  1. vector<vector<int>> levelOrder(TreeNode* root) {
  2. vector<vector<int>> results{};
  3. if( !root ) { return results; }
  4. // 用了两个队列交替进行,避免了记录数的深度
  5. // 每个队列的节点在同一深度,每次交替深度就会+1
  6. queue<TreeNode*> q1, q2;
  7. q1.push( root );
  8. TreeNode* tmpNode = nullptr;
  9. auto shit = [&]( queue<TreeNode*> &q_out, queue<TreeNode*> &q_in )
  10. {
  11. if( !q_out.empty() ) results.push_back( {} );
  12. auto &vec = results.back();
  13. while( !q_out.empty() )
  14. {
  15. tmpNode = q_out.front();
  16. q_out.pop();
  17. vec.push_back( tmpNode->val );
  18. if( tmpNode->left ) { q_in.push( tmpNode->left ); }
  19. if( tmpNode->right ) { q_in.push( tmpNode->right ); }
  20. }
  21. };
  22. while( !q1.empty() || !q2.empty() )
  23. {
  24. shit( q1, q2 );
  25. shit( q2, q1 );
  26. }
  27. return results;
  28. }

自底向上

题目:http://t.cn/A6LtHZ0o

  • 思路一
    • 将上面(自顶向下)的结果逆序。
  • 思路二
    • 相对更高效,用list结构代替vector结构,在list头部插入遍历的当前层的结果即可。vector在头部插入的效率很低。不过本地返回类型限制了vector。 ```cpp

vector> levelOrderBottom(TreeNode* root) { vector> results{};

  1. if( !root ) { return results; }
  2. queue<pair<TreeNode*, int>> q;
  3. q.push( { root, 0 } );
  4. TreeNode* tmpNode = nullptr;
  5. int tmpDepth = -1;
  6. while( !q.empty() )
  7. {
  8. auto data = q.front();
  9. tmpNode = data.first;
  10. tmpDepth = data.second;
  11. q.pop();
  12. if( tmpDepth == results.size() )results.push_back( {} );
  13. results[tmpDepth].push_back( tmpNode->val );
  14. if( tmpNode->left ) q.push( { tmpNode->left, tmpDepth + 1 } );
  15. if( tmpNode->right ) q.push( { tmpNode->right, tmpDepth + 1 } );
  16. }
  17. reverse(results.begin(), results.end());
  18. return results;

}

  1. <a name="rgOWB"></a>
  2. ## 场景三:之字形遍历
  3. 题目:[http://t.cn/A6VhF78F](http://t.cn/A6VhF78F)
  4. <a name="FlJ11"></a>
  5. ### 方法一
  6. 按场景二层序遍历,然后对偶数位置的vector进行逆序。
  7. ```cpp
  8. vector<vector<int> > zigzagLevelOrder( TreeNode* root )
  9. {
  10. vector<vector<int>> results{};
  11. if( !root ) { return results; }
  12. // 用了两个队列交替进行,避免了记录数的深度
  13. // 每个队列的节点在同一深度,每次交替深度就会+1
  14. queue<TreeNode*> q1, q2;
  15. q1.push( root );
  16. TreeNode* tmpNode = nullptr;
  17. auto shit = [&]( queue<TreeNode*> &q_out, queue<TreeNode*> &q_in )
  18. {
  19. if( !q_out.empty() ) results.push_back( {} );
  20. auto &vec = results.back();
  21. while( !q_out.empty() )
  22. {
  23. tmpNode = q_out.front();
  24. q_out.pop();
  25. vec.push_back( tmpNode->val );
  26. if( tmpNode->left ) { q_in.push( tmpNode->left ); }
  27. if( tmpNode->right ) { q_in.push( tmpNode->right ); }
  28. }
  29. };
  30. while( !q1.empty() || !q2.empty() )
  31. {
  32. shit( q1, q2 );
  33. shit( q2, q1 );
  34. }
  35. for( int i = 0; i < results.size(); i++ )
  36. {
  37. if( i & 0x1 ) { reverse( results[i].begin(), results[i].end() ); }
  38. }
  39. return results;
  40. }

方法二

类似层序遍历用两个queue,这里用两个stack代替。

  1. vector<vector<int> > zigzagLevelOrder( TreeNode* root )
  2. {
  3. vector<vector<int>> results{};
  4. if( !root ) { return results; }
  5. stack<TreeNode*> q1, q2;
  6. q1.push( root );
  7. TreeNode* tmpNode = nullptr;
  8. auto shit = [&]( stack<TreeNode*> &q_out, stack<TreeNode*> &q_in, bool flag )
  9. {
  10. if( !q_out.empty() ) results.push_back( {} );
  11. auto &vec = results.back();
  12. while( !q_out.empty() )
  13. {
  14. tmpNode = q_out.top();
  15. q_out.pop();
  16. vec.push_back( tmpNode->val );
  17. if( flag )
  18. {
  19. if( tmpNode->right ) { q_in.push( tmpNode->right ); }
  20. if( tmpNode->left ) { q_in.push( tmpNode->left ); }
  21. continue;
  22. }
  23. if( tmpNode->left ) { q_in.push( tmpNode->left ); }
  24. if( tmpNode->right ) { q_in.push( tmpNode->right ); }
  25. }
  26. };
  27. while( !q1.empty() || !q2.empty() )
  28. {
  29. shit( q1, q2, false );
  30. shit( q2, q1, true );
  31. }
  32. return results;
  33. }

场景四:N叉树的遍历

原理和二叉树类似,不过是对子节点访问有不同。