赞
踩
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]
提示:
[0, 100]
内-100 <= Node.val <= 100
**进阶:**递归算法很简单,你可以通过迭代算法完成吗?
class Solution { public: void preorder(TreeNode* root ,vector<int>& ans) { if(!root) return ; ans.push_back(root->val); preorder(root->left,ans); preorder(root->right,ans); } vector<int> preorderTraversal(TreeNode* root) { vector<int> ans; preorder(root,ans); return ans; } };
给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[3,2,1]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
[0, 100]
内-100 <= Node.val <= 100
**进阶:**递归算法很简单,你可以通过迭代算法完成吗?
class Solution { public: void postorder(TreeNode* root, vector<int>&ans) { if(!root) return; postorder(root->left,ans); postorder(root->right,ans); ans.push_back(root->val); } vector<int> postorderTraversal(TreeNode* root) { vector<int> ans; postorder(root,ans); return ans; } };
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
[0, 100]
内-100 <= Node.val <= 100
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
class Solution { public: void midorder(TreeNode *root,vector<int> &ans) { if(root == nullptr) return ; midorder(root->left,ans); ans.push_back(root->val); midorder(root->right,ans); } vector<int> inorderTraversal(TreeNode* root) { vector<int> ans; midorder(root,ans); return ans; } };
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> st; vector<int> ans; if (root == NULL) return ans; st.push(root); while(!st.empty()) { TreeNode * node = st.top(); st.pop(); ans.push_back(node->val); if(node->right)st.push(node->right); if(node->left)st.push(node->left); } return ans; } };
后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { stack<TreeNode*> st; vector<int> result; if (root == NULL) return result; st.push(root); while (!st.empty()) { TreeNode* node = st.top(); st.pop(); result.push_back(node->val); if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈) if (node->right) st.push(node->right); // 空节点不入栈 } reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了 return result; } };
在迭代的过程中,其实我们有两个操作:
分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。
那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。
那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
代码
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; stack<TreeNode*> st; TreeNode* cur = root; while (cur != NULL || !st.empty()) { if (cur != NULL) { // 指针来访问节点,访问到最底层 st.push(cur); // 将访问的节点放进栈 cur = cur->left; // 左 } else { cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据) st.pop(); result.push_back(cur->val); // 中 cur = cur->right; // 右 } } return result; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。