引言: 捷径是最长的路,偷来的巧,是致命的拙。若无递归,则尔多窘。
1.前序遍历(迭代)
解决思路: 使用栈模拟树的遍历. 顺序为根、左、右. 每个节点在入栈的时候便放入ret中,入栈表示访问根.因为树的遍历开始,拿的就是根.然后拿左子树中的根,右子树中的根...一种递归思想不知所言.
vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> s; vector<int> ret; while(!s.empty() || root) { if(root!=nullptr) { s.push(root); ret.push_back(root->val); root=root->left; } else { root=s.top(); s.pop(); if(root->right==nullptr) root=nullptr; else root=root->right; } } return ret; }
2.中序遍历(迭代)
解决思路: 使用栈模拟树的遍历,顺序为左、根、右.每个节点在出栈的时候放入ret.出栈表示访问左子树,因为树的遍历开始拿的是根,所以要先访问左子树,然后访问左子树的左子树,直到最左,然后是最左的根,最左的右,往上遍历..
vector<int> inorderTraversal(TreeNode* root) { stack<TreeNode*> s; vector<int> ret; while(!s.empty() || root) { while(root!=nullptr) { s.push(root); root=root->left; } root = s.top(); s.pop(); ret.push_back(root->val); if(root->right==nullptr) { root=nullptr; } else { root=root->right; } } return ret; }
3.后序遍历(迭代)
解决思路1: 用栈模拟树的遍历,顺序是左、右、根.每个节点出栈并且右子树已经走过才放入ret.要确保右子树访问过,需要实现一个标记记录走过的右子树.
vector<int> postorderTraversal(TreeNode* root) { stack<TreeNode*> s; vector<int> ret; TreeNode* rp = nullptr; while(!s.empty()||root) { while(root) { s.push(root); root=root->left; } root = s.top(); //结束的条件即右节点返回. 记录每次返回的右节点就知道根什么时候能输出了 if(root->right==nullptr || rp==root->right) { ret.push_back(root->val); rp = root; s.pop(); root=nullptr; } else { root = root->right; } } return ret; }
解决思路2: 模拟栈实现树的遍历. 顺序是根、右、左. 对结果进行反转即为所得: 左、右、中
vector<int> postorderTraversal(TreeNode* root) { stack<TreeNode*> s; vector<int> ret; while(!s.empty()||root) { if(root!=nullptr) { s.push(root); ret.push_back(root->val); root = root->right; } else { root = s.top(); s.pop(); if(root->left==nullptr) { root = nullptr; } else { root = root->left; } } } reverse(ret.begin(),ret.end()); return ret; }