Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

二叉树的中序遍历顺序为左-根-右,可以有递归和非递归来解,其中非递归解法又分为两种,一种是使用栈来接,另一种不需要使用栈。我们先来看递归方法,十分直接,对左子结点调用递归函数,根节点访问值,右子节点再调用递归函数,代码如下:

// Recursion
class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        vector<int> res;
        inorder(root, res);
        return res;
    }
    void inorder(TreeNode *root, vector<int> &res) {
        if (!root) return;
        if (root->left) inorder(root->left, res);
        res.push_back(root->val);
        if (root->right) inorder(root->right, res);
    }
};

下面我们再来看非递归使用栈的解法,也是符合本题要求使用的解法之一,需要用栈来做,思路是从根节点开始,先将根节点压入栈,然后再将其所有左子结点压入栈,然后取出栈顶节点,保存节点值,再将当前指针移到其右子节点上,若存在右子节点,则在下次循环时又可将其所有左子结点压入栈中。这样就保证了访问顺序为左-根-右,代码如下:

// Non-recursion
class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        vector<int> res;
        stack<TreeNode*> s;
        TreeNode *p = root;
        while (p || !s.empty()) {
            while (p) {
                s.push(p);
                p = p->left;
            }
            p = s.top();
            s.pop();
            res.push_back(p->val);
            p = p->right;
        }
        return res;
    }
};

下面我们来看另一种很巧妙的解法,这种方法不需要使用栈,所以空间复杂度为常量,这种非递归不用栈的遍历方法有个专门的名字,叫Morris Traversal,在介绍这种方法之前,我们先来引入一种新型树,叫 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指针指向其右子节点

// 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;
    }
};

其实Morris遍历不仅仅对中序遍历有用,对先序和后序同样有用,具体可参见网友NOALGO博客,和 Annie Kim's Blog的博客。所以对二叉树的三种常见遍历顺序(先序,中序,后序)就有三种解法(递归,非递归,Morris遍历),总共有九段代码呀,熟练掌握这九种写法才算初步掌握了树的遍历挖~~ 至于二叉树的层序遍历也有递归和非递归解法,至于有没有Morris遍历的解法还有待大神们的解答,若真有也请劳烦告知小弟一声~~

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Binary Tree Inorder Traversal 二叉树的中序遍历的更多相关文章

  1. [LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历

    Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...

  2. [LeetCode] Binary Tree Preorder Traversal 二叉树的先序遍历

    Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...

  3. lintcode:Binary Tree Postorder Traversal 二叉树的后序遍历

    题目: 二叉树的后序遍历 给出一棵二叉树,返回其节点值的后序遍历. 样例 给出一棵二叉树 {1,#,2,3}, 1 \ 2 / 3 返回 [3,2,1] 挑战 你能使用非递归实现么? 解题: 递归程序 ...

  4. leetcode题解:Binary Tree Postorder Traversal (二叉树的后序遍历)

    题目: Given a binary tree, return the postorder traversal of its nodes' values. For example:Given bina ...

  5. 94 Binary Tree Inorder Traversal(二叉树中序遍历Medium)

    题目意思:二叉树中序遍历,结果存在vector<int>中 解题思路:迭代 迭代实现: /** * Definition for a binary tree node. * struct ...

  6. Leetcode Binary Tree Inorder Traversal

    Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tre ...

  7. leetcode Binary Tree Inorder Traversal python

    # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = ...

  8. leetcode Binary Tree Postorder Traversal 二叉树后续遍历

    先给出递归版本的实现方法,有时间再弄个循环版的.代码如下: /** * Definition for binary tree * struct TreeNode { * int val; * Tree ...

  9. 49. leetcode 94. Binary Tree Inorder Traversal

    94. Binary Tree Inorder Traversal    二叉树的中序遍历 递归方法: 非递归:要借助栈,可以利用C++的stack

随机推荐

  1. 定位框一闪而过 iOS Swift

    需求:获取经纬度. 方案:我自定义了一个类模块CLLocationModule.swift 备注以下代码里 let IS_IOS8 = (UIDevice.currentDevice().system ...

  2. 【Java学习笔记】foreach语句(高级for)

    package p2; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java ...

  3. 图论 ---- spfa + 链式向前星 ---- poj 3268 : Silver Cow Party

    Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12674   Accepted: 5651 ...

  4. UIkit框架之UIwebview

    1.继承链:UIview:UIResponder:NSObject 2.使用loadHTMLString:baseURL:方法来加载本地的HTML文件,或者使用 loadRequest:方法来加载网络 ...

  5. SQLServer2008R2 mdf文件还原数据库

    偶然遇到要用mdf文件restore数据库,试了2个小时才弄出来,百度查出来的我试了都不太好用,或者是我没理解. 下面把我用的记录一下,以防忘记. 工具:SQLServer 2008R2 步骤: 1. ...

  6. SQL删除重复数据方法

    例如: id           name         value 1               a                 pp 2               a           ...

  7. Nginx+Tomcat实现反向代理及动静分离

    Nginx+Tomcat实现反向代理及动静分离 时间 2014-07-07 15:18:35  51CTO推荐博文 原文  http://yijiu.blog.51cto.com/433846/143 ...

  8. 类找不到异常 Caused by: java.lang.NoClassDefFoundError

    错误原因:在部署应用的时候,服务器报错,Caused by: java.lang.ClassNotFoundException: org.quartz.impl.JobDetailImpl,某个类找不 ...

  9. [ActionScript 3.0] AS3中的位图(BitmapData)应用

    1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xffffff); //画 ...

  10. asp.net 生成PDF方法

    今天转博客园看到有人发表了一篇生成PFd的文章,准备自己也留一份准备以后用到的时候方便调用: 首先去itextsharp网站下载控件(https://sourceforge.net/projects/ ...