LeetCode94. Binary Tree Inorder Traversal

题目 

给定一个二叉树,返回它的中序 遍历。

示例:

输入: [1,null,2,3]
   1
    \
     2
    /
   3

输出: [1,3,2]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?


考点

stack

递归

中序遍历:左-根-右


思路

ref:二叉树的前中后和层序遍历详细图解(递归和非递归写法)

1.递归

若根节点为空,返回。左子树调用递归。输出根节点。右子树调用递归。

2.非递归,用栈

从根节点开始,先将根节点压入栈,然后再将其所有左子结点压入栈,然后取出栈顶节点,保存节点值,再将当前指针移到其右子节点上,若存在右子节点,则在下次循环时又可将其所有左子结点压入栈中。这样就保证了访问顺序为左-根-右。

 

3.线索二叉树

ref:Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)

wiki:Threaded binary tree

A binary tree is threaded by making all right child pointers that would normally be null point to the inorder successor of the node (if it exists), and all left child pointers that would normally be null point to the inorder predecessor of the node.

把所有原本为空的右子节点指向了中序遍历之后的那个节点,

把所有原本为空的左子节点指向了中序遍历之前的那个节点,

构建一个线索二叉树,我们需要将所有为空的右子节点指向中序遍历的下一个节点,这样我们中序遍历完左子结点后,就能顺利的回到其根节点继续遍历了。

1. 初始化指针cur指向root

2. 当cur不为空时

  - 如果cur没有左子结点

      a) 打印出cur的值

    b) 将cur指针指向其右子节点

  - 反之

     将pre指针指向cur的左子树中的最右子节点 

     * 若pre不存在右子节点

          a) 将其右子节点指回cur

        b) cur指向其左子节点

     * 反之

      a) 将pre的右子节点置空

      b) 打印cur的值

      c) 将cur指针指向其右子节点

 


代码

1.递归

//递归:对左子节点调用递归,访问根,对右子树调用递归
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        order(root,ret);
        return ret;
    }

    void order(TreeNode* root,vector<int>& ret)
    { 
        if(!root) return;
        order(root->left,ret);
        ret.push_back(root->val);
        order(root->right,ret);
    } 
};

2.非递归+栈

//非递归:用栈
//1.先从根节点开始,遍历左子树,把经过的节点都压入栈,直到p到达最左节点。
//2.将栈顶元素输出,把当前节点指向栈顶元素右节点,弹出栈顶元素。
//3.如果当前节点存在或者栈不为空,循环1,2步骤,
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) { 
        vector<int> ret;
        stack<TreeNode*> s;
        TreeNode* curNode=root;
        while(curNode||!s.empty())//迭代条件:栈不为空,且还有节点没访问到
        {
            //遍历所有left,经历过的全入栈,找到最左节点
            while(curNode)
            {
                s.push(curNode);
                curNode=curNode->left;
            }

            //由于最左节点没有左子树,所以相当于是子结构树的根节点,中序遍历再访问右子树,重复1,2步

            //得到最左节点(栈顶)
            curNode=s.top();
            //输出最左节点
            ret.push_back(curNode->val);
            //出栈
            s.pop();

            //访问最左节点的右子树
            curNode=curNode->right;
        }
        return ret; 
    }
};

3.看不懂的解法。线索二叉树。

// Non-recursion and no stack
class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        vector<int> res;
        if (!root) return res;
        TreeNode *cur, *pre;
        cur = root;
        while (cur) {
            if (!cur->left) {
                res.push_back(cur->val);
                cur = cur->right;
            } else {
                pre = cur->left;
                while (pre->right && pre->right != cur) pre = pre->right;
                if (!pre->right) {
                    pre->right = cur;
                    cur = cur->left;
                } else {
                    pre->right = NULL;
                    res.push_back(cur->val);
                    cur = cur->right;
                }
            }
        }
        return res;
    }
};

问题

posted @ 2019-02-22 00:08 lightmare 阅读(...) 评论(...) 编辑 收藏