# 0094. Binary Tree Inorder Traversal ###### tags: `Leetcode` `Medium` `HashMap` Link: https://leetcode.com/problems/binary-tree-inorder-traversal/ ## 思路 这一题就是给一棵树,然后规定你读的顺序(先读左子树,再读root,再读右子树),然后按顺序把读到的东西印出来 ### 方法一 递归 ### 方法二 用一个stack来实现递归 ### 方法三 **Morris 中序遍历** Morris 遍历算法整体步骤如下(假设当前遍历到的节点为 x): 如果 x 无左孩子,先将 x 的值加入答案数组,再访问 x 的右孩子,即 *x = x=x.right*。 如果 x 有左孩子,则找到 x 左子树上最右的节点(即左子树中序遍历的最后一个节点,x 在中序遍历中的前驱节点),我们记为 *predecessor*。根据 *predecessor* 的右孩子是否为空,进行如下操作。 如果 *predecessor* 的右孩子为空,则将其右孩子指向 x,然后访问 x 的左孩子,即 *x = x.left*。 如果 *predecessor* 的右孩子不为空,则此时其右孩子指向 x,说明我们已经遍历完 x 的左子树,我们将 *predecessor* 的右孩子置空,将 x 的值加入答案数组,然后访问 x 的右孩子,即 *x = x.right*。 重复上述操作,直至访问完整棵树。 其实整个过程我们就多做一步:假设当前遍历到的节点为 x,将 x 的左子树中最右边的节点的右孩子指向 x,这样在左子树遍历完成后我们通过这个指向走回了 x,且能通过这个指向知晓我们已经遍历完成了左子树,而不用再通过栈来维护,省去了栈的空间复杂度。 ## Code ### 方法一 ```c= class Solution { public: void inorder(TreeNode* root, vector<int>& ans){ if(!root){ return; } inorder(root->left, ans); ans.push_back(root->val); inorder(root->right, ans); } vector<int> inorderTraversal(TreeNode* root) { vector<int> ans; inorder(root, ans); return ans; } }; ``` ### 方法二 ```c= class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> ans; stack<TreeNode*> stk; while(root!=nullptr || !stk.empty()){ while(root!=nullptr){ stk.push(root); root = root->left; } root = stk.top(); stk.pop(); ans.push_back(root->val); root = root->right; } return ans; } }; ``` ### 方法三 **注意不能漏掉第二个while里面的predecessor->right != root的条件,否则会进入无限回圈** eg: root在2处,找predecessor时,先往左走到4如果再往右走就会回到2。  ```c= class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> ans; TreeNode *predecessor = nullptr; while (root != nullptr) { if (root->left != nullptr) { // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止 predecessor = root->left; while(predecessor->right != nullptr && predecessor->right != root){ predecessor = predecessor->right; } // 让 predecessor 的右指针指向 root,继续遍历左子树 if (predecessor->right == nullptr) { predecessor->right = root; root = root->left; } // 说明左子树已经访问完了,我们需要断开链接 else { predecessor->right = nullptr; ans.push_back(root->val); root = root->right; } } // 如果没有左孩子,则直接访问右孩子 else { ans.push_back(root->val); root = root->right; } } return ans; } }; ``` ## Result ### 方法一 Runtime: 0 ms, faster than **100.00%** of C++ online submissions for Binary Tree Inorder Traversal. Memory Usage: 8.2 MB, less than **82.50%** of C++ online submissions for Binary Tree Inorder Traversal. ### 方法二 Runtime: 0 ms, faster than **100.00%** of C++ online submissions for Binary Tree Inorder Traversal. Memory Usage: 8.3 MB, less than **56.78%** of C++ online submissions for Binary Tree Inorder Traversal. ### 方法三 Runtime: 0 ms, faster than **100.00%** of C++ online submissions for Binary Tree Inorder Traversal. Memory Usage: 8.3 MB, less than **82.50%** of C++ online submissions for Binary Tree Inorder Traversal.
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up