递归算法C++代码:

 /**
* 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> tra;
Morder(root,tra);
return tra;
}
void Morder(TreeNode* root,vector<int> &tra){
if(root==NULL) return;
if(root->left)
Morder(root->left,tra);
tra.push_back(root->val);
if(root->right)
Morder(root->right,tra);
}
};

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

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

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

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/**
迭代法:具象描述递归执行过程
1)检查当前p是否为NULL,如果非NULL,当前节点入栈,只要当前节点有左子节点,左子节点入栈;
2)1之后,取栈顶元素p,由于1的操作,p没有左子节点,那么访问当前节点的值,且p出栈;
3)接下来访问右节点,p=p->right,如果右子节点存在,那么入栈,循环结束;
**/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root==NULL) return {};
vector<int>res;
stack<TreeNode*>s;
TreeNode*p=root;
s.push(p);
while(!s.empty()){
while(p&&p->left){
p=p->left;s.push(p);
} p=s.top();
res.push_back(p->val);s.pop(); //此处先令p=p->right,p可用作第一个while判断是向下递归还是回溯,如果递归过程p为非空,如果为NULl则代表回溯,那么下一轮不用向左递归;
p=p->right;
if(p) s.push(p);
}
return res;
}
};

别人的代码:

 /**
* 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> res;
stack<TreeNode*> st;
TreeNode* T=root;
while(T||!st.empty()){
//将T的所有左孩子入栈
while(T){
st.push(T);
T=T->left;
}
//访问T的元素,然后转到T的右孩子
if(!st.empty()){
T=st.top();
st.pop();
res.push_back(T->val);
T=T->right;
}
}
return res;
}
};

方法三: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)时间复杂度

 /**
* 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) {
//Morris Traversal:右线索化+回溯
vector<int> res;
if(!root) return res;
TreeNode *p=root; while(p){
//定义两个节点指针变量p和p的左孩子pLeft
TreeNode *pLeft=p->left;
if(pLeft){
//访问p的左孩子的最右子孩子(即pLeft右孩子的右孩子的右孩子...)
//线索化之前pLeft的最右子孩子的right指针指向NULL,
//线索化之后pLeft的最右子孩子的right指向中序遍历中该节点的后继节点p
//所以循环终止条件为pLeft->right==NULL 或 pLeft->right==p
while(pLeft->right && pLeft->right!=p){
pLeft=pLeft->right;
}
//此时pLeft代表p的左孩子的最右子孩子
//pLeft->right==NULL代表没有被线索化,进行线索化然后访问p的左孩子
if(pLeft->right==NULL){
pLeft->right=p;
p=p->left;
continue;
}
//pLeft->right!=NULL代表已经被线索化,此时已经回溯到原来的节点p(第2次访问),所以要恢复被线索化的pLeft的最右子孩子
else{
pLeft->right=NULL;
}
}
res.push_back(p->val);
p=p->right;//访问右孩子(对非叶节点),回溯到中序遍历的后续节点(对叶节点);
//因为线索化的操作最终是对所有的叶节点进行的,所以上述语句实际有访问右孩子和回溯两个功能;
}
return res;
}
};

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. 运维都该会的Socket知识!

    本篇博客转自赵班长 所有运维都会的Socket知识!!! 原创: 赵班长 新运维社区 什么是Socket? 大家都用电脑上网,当我们访问运维社区https://www.unixhot.com的时候,我 ...

  2. C语言字符串操作小结

    1)字符串操作strcpy(p, p1) 复制字符串strncpy(p, p1, n) 复制指定长度字符串strcat(p, p1) 附加字符串strncat(p, p1, n) 附加指定长度字符串s ...

  3. wireshark 抓usb包

    https://www.freebuf.com/articles/system/96216.html https://blog.csdn.net/shiailan/article/details/97 ...

  4. 第二章 Vue快速入门-- 25 过滤器-定义格式化时间的全局过滤器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  5. selenium-Xpath使用方法

    01:什么是Xpath Xpath是一门xml文档中查找信息的语言,Xpath可用来在xml文档中对元素和属性进行遍历,主流的浏览器都支持xpath,因为HTML页面在DOM中表示xhtml文档 xp ...

  6. POJ3415Common Substrings(后缀自动机)

    A substring of a string T is defined as:                 T( i, k)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| ...

  7. Acwing-279-自然数拆分(背包)

    链接: https://www.acwing.com/problem/content/281/ 题意: 给定一个自然数N,要求把N拆分成若干个正整数相加的形式,参与加法运算的数可以重复. 求拆分的方案 ...

  8. JS拖动滑块验证

    使用这种验证方法的目的:证明当前的用户不是机器人~防止恶意操作. 实现思路: 1.获取silde滑块(获取元素) 2.为元素注册事件———鼠标点击事件(onmousedown)鼠标点击之后获得当前鼠标 ...

  9. [人物存档]【AI少女】【捏脸数据】现代风格

    点击下载:6543d037acaf2edd03b4679f821001e9380193ce.png

  10. wx小程序知识点(三)

    三.封装小程序的数据请求 (1)在根目录创建utils目录,创建config.js.base.js (2)在config.js中创建config类,并将请求路径配置给config的属性restUrl, ...