leetcode 94二叉树的中序遍历

递归算法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二叉树的中序遍历的更多相关文章
- LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)
94. 二叉树的中序遍历 94. Binary Tree Inorder Traversal 题目描述 给定一个二叉树,返回它的 中序 遍历. LeetCode94. Binary Tree Inor ...
- Java实现 LeetCode 94 二叉树的中序遍历
94. 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? / ...
- Leetcode 94. 二叉树的中序遍历
1.问题描述 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 2.解法一 ...
- LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)
题目描述 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 由于 ...
- 【leetcode 94. 二叉树的中序遍历】解题报告
前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> inorderTraversal(TreeNode* root ...
- LeetCode 94 ——二叉树的中序遍历
1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 递归得到其左子树的数据向量 temp,将 temp 合并到 data 中去 将当前节 ...
- 【LeetCode】94. 二叉树的中序遍历
94. 二叉树的中序遍历 知识点:二叉树:递归:Morris遍历 题目描述 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 示例 输入:root = [1,null,2,3] 输出:[1, ...
- Leetcode题目94.二叉树的中序遍历(中等)
题目描述: 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路解析: 1 ...
- leetcode刷题-94二叉树的中序遍历
题目 给定一个二叉树,返回它的中序 遍历. 实现 # def __init__(self, x): # self.val = x # self.left = None # self.right = N ...
随机推荐
- python学习之路入门篇
本文是up学习python过程中遇到的一些问题及总结归纳,本小节是入门篇. python基本语法 循环.分支不多赘述. 模块:一个.py文件就是一个模块. 文件和异常 模式 含义解释 “r” 读模式 ...
- 内存不足导致mysql关闭,CentOS6.5增加swap分区
某日发现mysql自动关闭了,查找错误日志发现以下错误 2017-07-14 13:07:30 5494 [Note] InnoDB: Initializing buffer pool, size = ...
- openxlsx模块
import openpyxl #创建工作簿 wb = openpyxl.Workbook()#获取当前活跃的工作表 ws = wb.active#删除工作表 remove_sheet(wb.get_ ...
- windows时钟服务设置
运行Regedit,打开注册表编辑器. 找到注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config\,将Anno ...
- 关于join
- C#中引用参数ref和输出参数out
引用参数 用于按引用传递自变量. 为引用参数传递的自变量必须是具有明确值的变量,并且在方法执行期间,引用参数指明的存储位置与自变量相同. 引用参数使用 ref 修饰符进行声明. 输出参数 用于按引用传 ...
- qt类表
- Oracle数据库体系结构-Shared Pool
Oracle数据库简单介绍 对象关系型数据库 重点:一致性+性能 一致性优于性能 处理模型:C/S模型 Client:用户和用户进程 Server:服务器进程,实例,数据库本身 ...
- 利用jquery 实现菜单控制对应视图的显示与隐藏
效果: <!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta ...
- QT:提高QT Creator编译速度,配置预编译头Stable.h
提高QT Creator编译速度,配置预编译头Stable.h QT Creator支持预编译头提高编辑速度,网上有些教程写得不详细,走了弯路,具体实现方法如下. (1)工程.PRO文件加入下面代码 ...