前中后遍历 递归版

  /*  Recursive solution */
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) { vector<int> result;
preorderTraversal(root, result); return result;
} void preorderTraversal(TreeNode *root, vector<int>& result)
{
if(root == NULL) return;
result.push_back(root->val); preorderTraversal(root->left, result);
preorderTraversal(root->right, result);
} };
  /*  Recursive solution */
class Solution {
public:
vector<int> inorderTraversal(TreeNode *root) { vector<int> result;
inorderTraversal(root, result); return result;
} void inorderTraversal(TreeNode *root, vector<int>& result)
{
if(root == NULL) return; inorderTraversal(root->left, result);
result.push_back(root->val);
inorderTraversal(root->right, result);
} };
  /*  Recursive solution */
class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) { vector<int> result;
postorderTraversal(root, result); return result;
} void postorderTraversal(TreeNode *root, vector<int>& result)
{
if(root == NULL) return; postorderTraversal(root->left, result);
result.push_back(root->val);
postorderTraversal(root->right, result);
} };

下面是迭代版本

1 preorder: 节点入栈一次, 入栈之前访问。

2 inorder:节点入栈一次,出栈之后访问。

3 postorder:节点入栈2次,第二次出战后访问。

 class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) { vector<int> result;
stack<TreeNode*> stack; TreeNode *p = root; while( NULL != p || !stack.empty())
{
while(NULL != p)
{
result.push_back(p->val); stack.push(p);
p = p->left;
} if(!stack.empty())
{
p= stack.top();
stack.pop(); p=p->right;
}
} return result;
} };
 class Solution {
public:
vector<int> inorderTraversal(TreeNode *root) { vector<int> result;
stack<TreeNode*> stack; TreeNode *p = root; while( NULL != p || !stack.empty())
{
while(NULL != p)
{
stack.push(p);
p = p->left;
} if(!stack.empty())
{
p= stack.top();
stack.pop(); result.push_back(p->val); p=p->right;
}
} return result;
} };

后续, 用bStack标记是否是第一次访问,如果是第一次访问,再次入栈,否则直接访问,记得将P = NULL;

 class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) { vector<int> result;
stack<TreeNode*> stack;
std::stack<bool> bStack; TreeNode *p = root;
bool isFirst; while( NULL != p || !stack.empty())
{
while(NULL != p)
{
stack.push(p);
bStack.push(false);
p = p->left;
} if(!stack.empty())
{
p= stack.top();
stack.pop(); isFirst = bStack.top();
bStack.pop(); if(isFirst == )
{
stack.push(p);
bStack.push(true);
p=p->right;
}
else
{
result.push_back(p->val);
p = NULL;
} }
} return result;
} };

另外一种前序迭代实现

 class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
vector<int> result;
const TreeNode *p;
stack<const TreeNode *> s;
p = root;
if (p != nullptr) s.push(p);
while (!s.empty()) {
p = s.top();
s.pop();
result.push_back(p->val);
if (p->right != nullptr) s.push(p->right);
if (p->left != nullptr) s.push(p->left);
}
return result;
}
};

Morris 遍历

morris分为3个步骤,建立link,访问最左节点,删除link,morris前序和中序遍历只要调整在那里visit节点即可,框架相同。。

可以参考:http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html

Morris算法与递归和使用栈空间遍历的思想不同,它使用二叉树中的叶节点的right指针来保存后面将要访问的节点的信息,当这个right指针使用完成之后,再将它置为NULL,但是在访问过程中有些节点会访问两次,所以与递归的空间换时间的思路不同,Morris则是使用时间换空间的思想,先来看看Morris中序遍历二叉树的算法实现:

1 Morris 中序遍历

class Solution {
public:
void morris_inorder(TreeNode* T) {
TreeNode *p, *temp;
p = T;
while(p) {
if(p->left == NULL) {
printf("%4d \n", p->val);
p = p->right;
} else {
temp = p->left;
// find the most right node of the p's left node
while(temp->right != NULL && temp->right != p) {
temp = temp->right;
}
if(temp->right == NULL) {
temp->right = p;
p = p->left;
} else {
printf("%4d \n", p->val);
temp->right = NULL;
p = p->right;
}
}
}
}
};

同时, 以 下面的二叉树为例,走一遍流程:

      4

     /            \

2               7

/    \            /   \

1      3         5     8

p指向4,  temp指向2,然后while Loop,tmp指向3, 3->right = 4, p = p->left=2; 建立链接

p指向2, tmp指向1, 然后while Loop,tmp指向1,   1->right = 2, p = p->left = 1;建立链接

p指向1, 由于p->left == NULL,visit(1), p = p ->right = 2,

p指向2, tmp指向1, 然后while Loop,tmp指向1,  visit(2), 1->right = NULL, p = p->right = 3;断开链接

p指向3, 由于p->left == NULL,visit(3), p = p ->right = 4,

p指向4, tmp指向2, 然后while Loop,tmp指向3,  visit(4), 3->right = NULL, p = p->right = 7;断开链接

p指向7, tmp指向5, 然后while Loop,tmp指向5,   5->right = 7, p = p->left = 5;建立链接

p指向5, 由于p->left == NULL,visit(5), p = p ->right = 7,

p指向7, tmp指向5, 然后while Loop,tmp指向5,  visit(7), 5->right = NULL, p = p->right = 8;断开链接

p指向8, 由于p->left == NULL,visit(3), p = p ->right = NULL,

退出循环

加上些打印信息,更好理解

class Solution {
public:
void morris_inorder(TreeNode* T) {
TreeNode *p, *temp;
p = T;
while(p) {
if(p->left == NULL) {
printf("visit %4d \n", p->val);
p = p->right;
} else {
temp = p->left;
// find the most right node of the p's left node
while(temp->right != NULL && temp->right != p) {
temp = temp->right;
}
if(temp->right == NULL) {
cout << "build link for " << temp->val <<"-->" << p->val << endl;
temp->right = p;
p = p->left;
} else {
printf("visit %4d \n", p->val);
cout << "destory link for " << temp->val <<"-->" << p->val << endl;
temp->right = NULL;
p = p->right;
}
}
}
}
}; build link for -->
build link for -->
visit
visit
destory link for -->
visit
visit
destory link for -->
build link for -->
visit
visit
destory link for -->
visit

morris 前序遍历

        void morris_preorder(TreeNode* T) {
TreeNode *p, *temp;
p = T;
while(p) {
if(p->left == NULL) {//visit the leftmost leaf node
printf("visit %4d \n", p->val);
p = p->right;
} else {
temp = p->left;
// find the most right node of the p's left node
while(temp->right != NULL && temp->right != p) {
temp = temp->right;
}
if(temp->right == NULL) {//build the link
printf("visit %4d \n", p->val);
temp->right = p;
p = p->left;
} else {//remove the link
temp->right = NULL;
p = p->right;
}
}
}
}

3 morris 后序遍历

这里的reverse 和reverse单链表意思相同,另外之所以使用链表的reverse,而没有采用辅助stack后者vector是考虑要求空间复杂度O(1)的考虑

void reverse(TreeNode *from, TreeNode *to) // reverse the tree nodes 'from' -> 'to'.
{
if (from == to)
return;
TreeNode *x = from, *y = from->right, *z;
while (true)
{
z = y->right;
y->right = x;
x = y;
y = z;
if (x == to)
break;
}
} void printReverse(TreeNode* from, TreeNode *to) // print the reversed tree nodes 'from' -> 'to'.
{
reverse(from, to); TreeNode *p = to;
while (true)
{
printf("%d ", p->val);
if (p == from)
break;
p = p->right;
} reverse(to, from);
} void postorderMorrisTraversal(TreeNode *root) {
TreeNode dump();
dump.left = root;
TreeNode *cur = &dump, *prev = NULL;
while (cur)
{
if (cur->left == NULL)
{
cur = cur->right;
}
else
{
prev = cur->left;
while (prev->right != NULL && prev->right != cur)
prev = prev->right; if (prev->right == NULL)
{
prev->right = cur;
cur = cur->left;
}
else
{
printReverse(cur->left, prev); // call print
prev->right = NULL;
cur = cur->right;
}
}
}
}

还是以上述bst为例,走一遍code:

p指向dummy,  temp指向4,然后while Loop,tmp指向8, 8->right = dummy, p = p->left=4; 建立链接

p指向4,  temp指向2,然后while Loop,tmp指向3, 3->right = 4, p = p->left=2; 建立链接

p指向2, tmp指向1, 然后while Loop,tmp指向1,   1->right = 2, p = p->left = 1;建立链接

p指向1, 由于p->left == NULL, p = p ->right = 2,

p指向2, tmp指向1, 然后while Loop,tmp指向1,  reversePrint(1,1), 1->right = NULL, p = p->right = 3;断开链接

p指向3, 由于p->left == NULL, p = p ->right = 4,

p指向4, tmp指向2, 然后while Loop,tmp指向3,  reversePrint(2,3), 3->right = NULL, p = p->right = 7;断开链接

p指向7, tmp指向5, 然后while Loop,tmp指向5,   5->right = 7, p = p->left = 5;建立链接

p指向5, 由于p->left == NULL, p = p ->right = 7,

p指向7, tmp指向5, 然后while Loop,tmp指向5,  reversePrint(5,5), 5->right = NULL, p = p->right = 8;断开链接

p指向8, 由于p->left == NULL,, p = p ->right = dummy,

p指向dummy, tmp指向4, 然后while Loop,tmp指向8,  reversePrint(4,8), 8->right = NULL, p = p->right = null;断开链接

退出循环

[LeetCode] Binary Tree Preorder/Inorder/Postorder Traversal的更多相关文章

  1. LeetCode之“树”:Binary Tree Preorder && Inorder && Postorder Traversal

    Binary Tree Preorder Traversal 题目链接 题目要求: Given a binary tree, return the preorder traversal of its ...

  2. LC 144. / 94. / 145. Binary Tree Preorder/ Inorder/ PostOrder Traversal

    题目描述 144. Binary Tree Preorder Traversal 94. Binary Tree Inorder Traversal 145. Binary Tree Postorde ...

  3. 【题解】【BT】【Leetcode】Binary Tree Preorder/Inorder/Postorder (Iterative Solution)

    [Inorder Traversal] Given a binary tree, return the inorder traversal of its nodes' values. For exam ...

  4. LeetCode: Binary Tree Preorder Traversal 解题报告

    Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...

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

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

  6. [LeetCode] Binary Tree Preorder Traversal

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

  7. [leetcode]Binary Tree Preorder Traversal @ Python

    原题地址:http://oj.leetcode.com/problems/binary-tree-preorder-traversal/ 题意:这题用递归比较简单.应该考察的是使用非递归实现二叉树的先 ...

  8. LeetCode——Binary Tree Preorder Traversal

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

  9. LeetCode Binary Tree Preorder Traversal 先根遍历

    题意:给一棵树,求其先根遍历的结果. 思路: (1)深搜法: /** * Definition for a binary tree node. * struct TreeNode { * int va ...

随机推荐

  1. ASP.NET中进行消息处理(MSMQ) 三

    在本文的前两篇文章里对MSMQ的相关知识点进行了介绍,很多阅读过这前两篇文章的朋友都曾问到过这样一些问题:  1.如何把MSMQ应用到实际的项目中去呢?  2.可不可以介绍一个实际的应用实例?  3. ...

  2. Navicat for mysql 显示中文乱码问题

    使用navicat for mysql 打开数据库时,使用Console插入和查询数据显示乱码 处理过程 1.查看数据库编码为" utf8 -- UTF-8 Unicode",也就 ...

  3. python机器学习《回归 一》

    唠嗑唠嗑 依旧是每一次随便讲两句生活小事.表示最近有点懒,可能是快要考试的原因,外加这两天都有笔试和各种面试,让心情变得没那么安静的敲代码,没那么安静的学习算法.搞得第一次和技术总监聊天的时候都不太懂 ...

  4. MVVM开源框架Knot.js 教程1 - CBS初步

    Knotjs教程系列 1.CBS初步(本文) 2.Knot.js Debugger ....持续增加中 CBS初步 学习Knot.js,实际上就是学习如何使用CBS.CBS使用和CSS类似的原理,将绑 ...

  5. 如何使用Iveely的数据存储引擎 Iveely Database

    Iveely 数据存储引擎是为Iveely 搜索引擎提供数据存储的机制. 适用于:频繁数据插入.数据读取.数据更改或者删除数据不适合Iveely Database,存储结构是按照搜索引擎数据存储要求( ...

  6. Java学习笔记(十九)——Java 日志记录 AND log4j

    [前面的话] 学习的进度应该稍微在快一点. Java日志到了必须学习怎么使用的时候了,因为在项目中要进行使用.基础性文章,选择性阅读. [结构] java日志对调试,记录运行,问题定位都起到了很重要的 ...

  7. WINDOWS8.1安装ORACLE客户端及配置

    1.官方网站下载: instantclient-basic-win32-11.2.0.1.0.zip instantclient-sqlplus-win32-11.2.0.1.0.zip instan ...

  8. Bootstrap系列 -- 24. 下拉菜单基本用法

    在使用Bootstrap框架的下拉菜单时,必须调用Bootstrap框架提供的bootstrap.js文件.当然,如果你使用的是未编译版本,在js文件夹下你能找到一个名为“dropdown.js”的文 ...

  9. form表单用ge方式提交时ie显示中文参数乱码

    有网友说 通过给form表单添加accept-charset="gb2312"和 onsubmit="document.charset='gb2312'" 但这 ...

  10. 大型网站系统架构实践(六)深入探讨web应用集群Session保持

    原理 在第三,四篇文章中讲到了会话保持的问题,而且还遗留了一个问题,就是会话保持存在单点故障, 当时的方案是cookie插入后缀,即haproxy指负责分发请求,应用服务自行保持用户会话,如果应 用服 ...