二叉树的Morris遍历
二叉树的遍历,除了上篇文章中的传统递归和使用的栈结构的非递归方式,还有如下这种Morris遍历方式,该算法的构思非常巧妙:利用前驱空闲的rightChild指针指向当前节点,形成一个环。时间复杂度和前面两种一样,还是O(n),但是空间复杂度由O(n)直接下降到了O(1)。代码如下:
/*************************************************************************
> File Name: MorrisTraversal.c
> Description: 线索二叉树的实现
> Author: Yves
> E-mail:
> Created Time: 2015-5-23. 22:51:16
************************************************************************/ #include <stdio.h>
#include <stdlib.h> typedef char ElemType;
typedef struct tagBiTreeNode
{
ElemType data;
struct tagBiTreeNode* leftChild;
struct tagBiTreeNode* rightChild;
}BiTreeNode, *pBiTreeNode;//指向BiTNode的指针 static void CreatBiTree(pBiTreeNode *root);//创建二叉树
static void PreOrderMorrisTraversal(pBiTreeNode root);//前序Morris遍历
static void InOrderMorrisTraversal(pBiTreeNode root);//中序Morris遍历
static void PostOrderMorrisTraversal(pBiTreeNode root);//后序Morris遍历 pBiTNode pre; int main(void)
{
pBiTreeNode root;
printf("Please input the node of the tree(preorder sequence): ");
CreatBiTree(&root);
printf("Traverse the tree in PreOrderMorrisTraversal\n");
PreOrderMorrisTraversal(root);
printf("Traverse the tree in InOrderMorrisTraversal\n");
InOrderMorrisTraversal(root);
printf("Traverse the tree in PostOrderMorrisTraversal\n");
PostOrderMorrisTraversal(root) return ;
} static void CreatBiTree(pBiTreeNode *root)
{
ElemType c;
scanf("%c",&c);
if(c == '#')
{
*root = NULL;
}else
{
*root = (pBiTreeNode)malloc(sizeof(BiTreeNode));
(*root)->data = c;
CreatBiTree(&(*root)->leftChild);
CreatBiTree(&(*root)->rightChild);
}
} static void PreOrderMorrisTraversal(pBiTreeNode root)
{
if(root == NULL)
{
return;
}
pBiTreeNode cur,pre,temp;
cur = root;
while(cur != NULL)
{
if(!cur->leftChild)
{
printf("%c ", cur->data);
pre = cur;
cur = cur->rightChild;
}else
{
for(temp = cur->leftChild; temp->rightChild != NULL && temp->rightChild != cur; temp = temp->rightChild);
if(temp->rightChild == NULL)
{
temp->rightChild = cur;
printf("%c ", cur->data);
pre = cur;
cur = cur->leftChild;
}else
{ temp->rightChild = NULL;
cur = cur->rightChild;
}
}
}
} static void InOrderMorrisTraversal(pBiTreeNode root)
{
if(root == NULL)
{
return;
}
pBiTreeNode cur,pre,temp;
cur = root;
while(cur != NULL)
{
if(!cur->leftChild)
{
printf("%c ", cur->data);
pre = cur;
cur = cur->rightChild;
}else
{
for(temp = cur->leftChild; temp->rightChild != NULL && temp->rightChild != cur; temp = temp->rightChild);
if(temp->rightChild == NULL)
{
temp->rightChild = cur;
cur = cur->leftChild;
}else /*Meaning the left tree has been accessed completely.*/
{
printf("%c ", cur->data);
temp->rightChild = NULL;
pre = cur;
cur = cur->rightChild;
}
}
}
} static void PostOrderMorrisTraversal(pBiTreeNode root)
{
//coding
}
二叉树的Morris遍历的更多相关文章
- 【数据结构与算法】二叉树的 Morris 遍历(前序、中序、后序)
前置说明 不了解二叉树非递归遍历的可以看我之前的文章[数据结构与算法]二叉树模板及例题 Morris 遍历 概述 Morris 遍历是一种遍历二叉树的方式,并且时间复杂度O(N),额外空间复杂度O(1 ...
- Morris 遍历实现二叉树的遍历
Morris 遍历实现二叉树的遍历 作者:Grey 原文地址: 博客园:Morris 遍历实现二叉树的遍历 CSDN:Morris 遍历实现二叉树的遍历 说明 Morris 遍历可以实现二叉树的先,中 ...
- 二叉树的遍历(递归,迭代,Morris遍历)
二叉树的三种遍历方法: 先序,中序,后序,这三种遍历方式每一个都可以用递归,迭代,Morris三种形式实现,其中Morris效率最高,空间复杂度为O(1). 主要参考博客: 二叉树的遍历(递归,迭代, ...
- 二叉树的遍历(递归,迭代,Morris遍历)
二叉树的遍历: 先序,中序,后序: 二叉树的遍历有三种常见的方法, 最简单的实现就是递归调用, 另外就是飞递归的迭代调用, 最后还有O(1)空间的morris遍历: 二叉树的结构定义: struct ...
- 【转载】Morris遍历二叉树 & BST(二叉搜索树) Traverse & 空间O(1) 时间O(n)
因为做一道Leetcode的题目(前面博客有:link),需要用Space O(1)空间复杂度来中序遍历树, 看了Discuss,也上网搜了一下,发现空间O(1)可以用 Morris遍历的方法.方法介 ...
- 面试中很值得聊的二叉树遍历方法——Morris遍历
Morri遍历 通过利用空闲指针的方式,来节省空间.时间复杂度O(N),额外空间复杂度O(1).普通的非递归和递归方法的额外空间和树的高度有关,递归的过程涉及到系统压栈,非递归需要自己申请栈空间,都具 ...
- 算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序
接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public ...
- 经典算法 Morris遍历
内容: 1.什么是morris遍历 2.morris遍历规则与过程 3.先序及中序 4.后序 5.morris遍历时间复杂度分析 1.什么是morris遍历 关于二叉树先序.中序.后序遍历的递归和非递 ...
- Morris遍历
Morris遍历 一种遍历二叉树的方式,并且时间复杂度O(N),额外空间复杂度O(1) 通过利用原树中大量空闲指针的方式,达到节省空间的目的 Morris遍历可以改前中后序的树遍历 思路: 创建一个当 ...
随机推荐
- altium designer不经过原理图直接在空白pcb上加封装然后画线
如果是复杂点的PCB,建议还是画下SCH,如果PCB只有几个元件,那么可以用这种方法,想不画原理图,直接进行布线,往往是很多初学者最想知道的,但是这也一定不是初学者能学到的.因为你买的书,都是按画PC ...
- Delphi:窗体自适应屏幕分辨率(根据预设值的比例改变)
delphi 程序适应屏幕分辨率,先在表单单元的Interface部分定义两个常量, 表示设计时的屏幕的宽度和高度(以像素为单位). 在表单的Create事件中先判断 当前分辨率是否与设计分辨率相同, ...
- 设计模式(十二): Flyweight享元模式 -- 结构型模式
说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...
- Linux内核定时器
Linux使用struct timer_list来描述一个定时器. 重要成员: expires:定时时长 *function:超时执行函数名使用流程: 1.定义定时器变量 /*定义定时器变量结构 ...
- codevs1033 蚯蚓的游戏问题
题目描述 Description 在一块梯形田地上,一群蚯蚓在做收集食物游戏.蚯蚓们把梯形田地上的食物堆积整理如下: a(1,1) a(1,2)…a(1,m) a(2,1) a(2,2) a(2 ...
- HTTP response codes
面试被问起了413和503,我觉得也是够BT的,能问出这种无聊的问题.很多返回码几乎很难遇到,不过还是把MDN上很好的描述转过来作为一个reference. HTTP协议状态码表示的意思主要分为五类 ...
- Java 反射机制详解
动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化.比如众所周知的ECMAScript(JavaScript)便是一个动态语言.除此之外如Ru ...
- lesson8:AtomicInteger源码解析及性能分析
AtomicInteger等对象出现的目的主要是为了解决在多线程环境下变量计数的问题,例如常用的i++,i--操作,它们不是线程安全的,AtomicInteger引入后,就不必在进行i++和i--操作 ...
- ibatis的selectkey
在使用ibatis插入数据进数据库的时候,会用到一些sequence的数据,有些情况下,在插入完成之后还需要将sequence的值返回,然后才能进行下一步的操作. 使用ibatis的sel ...
- [ES6] Promise
How to use: export default function getReplies(topicId){ return new Promise(function( resolve, rejec ...