【leetcode】94. Binary Tree Inorder Traversal------Morris Traversal

首先谈谈树的三种遍历方式:

  • 前序遍历:根左右
  • 中序遍历:左根右
  • 后序遍历:左右根

关于Leetcode Binary Tree Inorder Traversal,这里讨论三种遍历方式:
  • 递归遍历             递归理论上也是O(n)的空间,因为递归需要用到栈
  • 迭代遍历             迭代需要用到队列来保存状态,空间复杂度为O(n)
  • Morris Traversal 此种方法特为巧妙,有点类似加入线索二叉树(threaded binary tree)的概念,空间复杂度O(1)

版本1:递归
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void inorder(TreeNode* root, vector<int>& vec) {
        if(root->left != NULL) inorder(root->left, vec);     // 左
        vec.push_back(root->val);                            // 根
        if(root->right != NULL) inorder(root->right, vec);   // 右
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> vec;
        if(root == NULL) return vec;
        inorder(root, vec);
        return vec;
    }
};

版本2: 迭代
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> vec;
        if(root == NULL) return vec;
        
        stack<TreeNode*> st;
        TreeNode *cur = root;
        while(!st.empty() || cur != NULL) { 
            while(cur != NULL) {     //不断先将左子树节点加入栈
                st.push(cur); 
                cur = cur->left;
            }
            cur = st.top();
            st.pop();
            vec.push_back(cur->val);
            cur = cur->right;
        }
        return vec;
    }
};

版本3. Morris Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> vec;
        if(root == NULL) return vec;
        
        TreeNode* cur = root;
        TreeNode* prev = NULL;
        
        while(cur) {
            // 如果当前左孩子为空,则其直接输出,并遍历设立右孩子为遍历节点
            if(cur->left == NULL) {
                vec.push_back(cur->val);
                cur = cur->right;
                continue;
            }
            
            // 如果左孩子不为空
            prev = cur->left;
            // 找到左孩子中的最右节点,也就是左子树值最大的节点
            while(prev->right != NULL && prev->right != cur) prev = prev->right;
            // 如果左子树值最大节点的右孩子为空,那么就将其指向当前cur,这样在下次遍历到
            // 此节点时,我们可以直接回溯到比左子树最大节点的下一个节点,也就是cur
            if(prev->right == NULL) {
                prev->right = cur;
                cur = cur->left;
            }
            // 如果当前已经指向了最右节点,那么此时说明已经遍历到了此节点,要还原二叉树
            // 因为原本指向的right的为NULL,并将cur回溯到原本的左子树位置。
            else {
                prev->right = NULL;
                vec.push_back(cur->val);
                cur = cur->right;
            }
        }
        return vec;
    }
};




你可能感兴趣的:(LeetCode,tree,traversal,traversal,Morris,Inorder)