递归算法C++代码:

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12. vector<int> inorderTraversal(TreeNode* root) {
  13. vector<int> tra;
  14. Morder(root,tra);
  15. return tra;
  16. }
  17. void Morder(TreeNode* root,vector<int> &tra){
  18. if(root==NULL) return;
  19. if(root->left)
  20. Morder(root->left,tra);
  21. tra.push_back(root->val);
  22. if(root->right)
  23. Morder(root->right,tra);
  24. }
  25. };

非递归方法(迭代):通过stack容器

C++代码:O(n)空间复杂度,O(n)时间复杂度

自己写的,实际上为将递归方法代码用stack具体化,需要注意的是加上了回溯与向下递归的判别;

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. /**
  11. 迭代法:具象描述递归执行过程
  12. 1)检查当前p是否为NULL,如果非NULL,当前节点入栈,只要当前节点有左子节点,左子节点入栈;
  13. 2)1之后,取栈顶元素p,由于1的操作,p没有左子节点,那么访问当前节点的值,且p出栈;
  14. 3)接下来访问右节点,p=p->right,如果右子节点存在,那么入栈,循环结束;
  15. **/
  16. class Solution {
  17. public:
  18. vector<int> inorderTraversal(TreeNode* root) {
  19. if(root==NULL) return {};
  20. vector<int>res;
  21. stack<TreeNode*>s;
  22. TreeNode*p=root;
  23. s.push(p);
  24. while(!s.empty()){
  25. while(p&&p->left){
  26. p=p->left;s.push(p);
  27. }
  28.  
  29. p=s.top();
  30. res.push_back(p->val);s.pop();
  31.  
  32. //此处先令p=p->right,p可用作第一个while判断是向下递归还是回溯,如果递归过程p为非空,如果为NULl则代表回溯,那么下一轮不用向左递归;
  33. p=p->right;
  34. if(p) s.push(p);
  35. }
  36. return res;
  37. }
  38. };

别人的代码:

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12. vector<int> inorderTraversal(TreeNode* root) {
  13. //使用栈的非递归方法
  14. vector<int> res;
  15. stack<TreeNode*> st;
  16. TreeNode* T=root;
  17. while(T||!st.empty()){
  18. //将T的所有左孩子入栈
  19. while(T){
  20. st.push(T);
  21. T=T->left;
  22. }
  23. //访问T的元素,然后转到T的右孩子
  24. if(!st.empty()){
  25. T=st.top();
  26. st.pop();
  27. res.push_back(T->val);
  28. T=T->right;
  29. }
  30. }
  31. return res;
  32. }
  33. };

方法三:Morris Traversal

由于需要用到Thread Binary  Tree(线索二叉树),参考 透彻理解线索二叉树 彻底理解线索二叉树

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

对于n个节点的二叉树,左右孩子指针为2n个,利用的指针为n-1个,没有利用的指针为n+1个;利用空链域存储前驱和后继:

记ptr指向二叉链表中的一个结点,以下是建立线索的规则:

(1)如果ptr->lchild为空,则存放指向中序遍历序列中该结点的前驱结点。这个结点称为ptr的中序前驱;

(2)如果ptr->rchild为空,则存放指向中序遍历序列中该结点的后继结点。这个结点称为ptr的中序后继;

当然,Morris遍历只用到了线索二叉树的思想和部分操作,线索二叉树的更细节的东西此处不赘述。对于本题,实际上只用到了对叶节点的右指针的线索化,以及通过线索化的指针进行回溯。主要有以下两点:

#1 对所有叶节点的右指针的线索化,令其指向中序遍历的后继节点;

#2 通过线索化的节点,访问中序遍历的后继节点,并恢复被线索化的节点;

参考:二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历

C++代码如下:O(1)空间复杂度,O(n)时间复杂度

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  8. * };
  9. */
  10. class Solution {
  11. public:
  12. vector<int> inorderTraversal(TreeNode* root) {
  13. //Morris Traversal:右线索化+回溯
  14. vector<int> res;
  15. if(!root) return res;
  16. TreeNode *p=root;
  17.  
  18. while(p){
  19. //定义两个节点指针变量p和p的左孩子pLeft
  20. TreeNode *pLeft=p->left;
  21. if(pLeft){
  22. //访问p的左孩子的最右子孩子(即pLeft右孩子的右孩子的右孩子...)
  23. //线索化之前pLeft的最右子孩子的right指针指向NULL,
  24. //线索化之后pLeft的最右子孩子的right指向中序遍历中该节点的后继节点p
  25. //所以循环终止条件为pLeft->right==NULL 或 pLeft->right==p
  26. while(pLeft->right && pLeft->right!=p){
  27. pLeft=pLeft->right;
  28. }
  29. //此时pLeft代表p的左孩子的最右子孩子
  30. //pLeft->right==NULL代表没有被线索化,进行线索化然后访问p的左孩子
  31. if(pLeft->right==NULL){
  32. pLeft->right=p;
  33. p=p->left;
  34. continue;
  35. }
  36. //pLeft->right!=NULL代表已经被线索化,此时已经回溯到原来的节点p(第2次访问),所以要恢复被线索化的pLeft的最右子孩子
  37. else{
  38. pLeft->right=NULL;
  39. }
  40. }
  41. res.push_back(p->val);
  42. p=p->right;//访问右孩子(对非叶节点),回溯到中序遍历的后续节点(对叶节点);
  43. //因为线索化的操作最终是对所有的叶节点进行的,所以上述语句实际有访问右孩子和回溯两个功能;
  44. }
  45. return res;
  46. }
  47. };

leetcode 94二叉树的中序遍历的更多相关文章

  1. LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)

    94. 二叉树的中序遍历 94. Binary Tree Inorder Traversal 题目描述 给定一个二叉树,返回它的 中序 遍历. LeetCode94. Binary Tree Inor ...

  2. Java实现 LeetCode 94 二叉树的中序遍历

    94. 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? / ...

  3. Leetcode 94. 二叉树的中序遍历

    1.问题描述 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 2.解法一 ...

  4. LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)

    题目描述 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 由于 ...

  5. 【leetcode 94. 二叉树的中序遍历】解题报告

    前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> inorderTraversal(TreeNode* root ...

  6. LeetCode 94 ——二叉树的中序遍历

    1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 递归得到其左子树的数据向量 temp,将 temp 合并到 data 中去 将当前节 ...

  7. 【LeetCode】94. 二叉树的中序遍历

    94. 二叉树的中序遍历 知识点:二叉树:递归:Morris遍历 题目描述 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 示例 输入:root = [1,null,2,3] 输出:[1, ...

  8. Leetcode题目94.二叉树的中序遍历(中等)

    题目描述: 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路解析: 1 ...

  9. leetcode刷题-94二叉树的中序遍历

    题目 给定一个二叉树,返回它的中序 遍历. 实现 # def __init__(self, x): # self.val = x # self.left = None # self.right = N ...

随机推荐

  1. 配置maven的国内镜像

    pom.xml文件出现错误标记,一般是相关的maven资源没有下载完整. 1,配置maven的国内镜像,保证能够顺利下载maven中配置的资源. 在maven的配置文件  settings.xml  ...

  2. selenium入门学习

    在写爬虫的学习过程中,经常会有一些动态加载,有些是可以动过接口直接获取到,但是实在没办法,所以学习下selenium. 首先百度一下: Selenium [1]  是一个用于Web应用程序测试的工具. ...

  3. @Validated @RequestBody @RequestParam配合使用校验参数

    1.  @Validated @RequestBody 配合使用 两者搭配进行参数的校验,要想自己捕获该异常,需要自定义全局异常处理器 2.  @Validated @RequestParam 配合使 ...

  4. Java程序员常用的Linux命令01——linux命令基础

    1.显示日期的命令date 显示日期: [root@localhost ~]# date 显示年月日: [root@localhost ~]# date '+%Y%m%d' 2.显示日历指令cal 显 ...

  5. 网络初级篇之OSPF(二)实验

    一.实验目的:     下面关于OSPF的实验,仔细看配置过程,以增加对OSPF的理解. 二.实现目标:     使用OSPF实现所有主机之间的通信 三.配置过程: 1.AR1的配置过程:      ...

  6. c++ 实现https网页上的图片爬取

    一.主要的原理 我们通过发送一个http请求,获得目标网页的html源代码,然后通过正则表达式获取到图片的URL,把该网页的所有的图片都保存到一个文件夹,这就是整个软件的流程. 二.具体的实践 现在很 ...

  7. Codeforces Round #344 (Div. 2) 631 C. Report (单调栈)

    C. Report time limit per test2 seconds memory limit per test256 megabytes inputstandard input output ...

  8. html base标签 target=_parent使用介绍

    <base>标签为页面上的所有链接规定默认地址或默认目标. 通常情况下,浏览器会从当前文档的URL中提取相应的元素来填写相对URL中的空白. 使用<base> 标签可以改变这一 ...

  9. Django学习系列17:在模板中渲染待办事项

    前面提到的问题中在表格中显示多个待办事项 是最后一个容易解决的问题.要编写一个新单元测试,检查模板是否也能显示多个待办事项: lists/tests.py def test_displays_all_ ...

  10. nginx-轮询、权重、ip_hash 、fair模式

    在 linux 下有 Nginx.LVS.Haproxy 等等服务可以提供负载均衡服 务,而且 Nginx 提供了几种分配方式(策略): 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器 ...