首先来递归算法,简单易懂:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> typedef struct TreeNode{
char data;
struct TreeNode *lchild, *rchild;
}TreeNode; void PreOrderTraverse(TreeNode *t){
if( NULL == t ) return;
printf("%c",t->data);
PreOrderTraverse(t->lchild);
PreOrderTraverse(t->rchild);
}

  然后是栈模拟递归:

typedef struct StackNode{
TreeNode *pdata;
struct StackNode *next;
}StackNode;
typedef struct Stack{
StackNode *top;
}Stack; Stack *init_s(){
Stack *pnew = (Stack *)malloc(sizeof(Stack));
pnew->top = NULL;
return pnew;
}
void push(Stack *s,TreeNode *p){
StackNode *pnew = (StackNode *)malloc(sizeof(StackNode));
pnew->pdata = p;
pnew->next = s->top;
s->top = pnew;
}
bool empty_stack(Stack *s){
return NULL == s->top;
}
TreeNode *pop(Stack *s){
TreeNode *p = NULL;
StackNode *pn = NULL;
if( ! empty_stack(s) ){
pn = s->top;
p = pn->pdata;
s->top = pn->next;
free(pn);
}
return p;
}
void PreOrderTraverse(TreeNode *t){
if( NULL == t ) return;
TreeNode *p = NULL;
Stack *s = init_s();
push(s,t);
while( ! empty_stack(s) ){
p = pop(s);
if( NULL == p ){
continue;
}
printf("%c",p->data);
push(s,p->rchild);
push(s,p->lchild);
}
}

  Morris Traversal算法:空间复杂度O(1):

  用线索二叉树(threaded binary tree)的概念,利用叶子的左右闲指针指向遍历的前驱或者后继节点。

  算法如下:

  1、初始化当前节点为root
  2、若当前节点不为空
    a) 若当前节点没有左孩子
      访问当前节点,并将当前节点移向右孩子
    b) 若当前节点有左孩子
      找到左子树的最右边那个节点
      若它的右指针为空,访问当前节点,把它的右指针指向cur,并移动到当前节点到左孩子
      若它的右指针为当前节点,则把它的右指针重新设为空(恢复树),并移动到当前节点的右孩子
  3、重复第2步

void PreOrderTraverse(TreeNode *t){
if( NULL == t ) return;
TreeNode *pcur = t, *pre = NULL;
while( pcur ){
if( pcur->lchild ){
pre = pcur->lchild;
while( pcur != pre->rchild && NULL != pre->rchild ){
pre = pre->rchild;
}
if( pre->rchild == pcur ){
pre->rchild = NULL;
pcur = pcur->rchild;
}
else{
printf("%c",pcur->data);
pre->rchild = pcur;
pcur = pcur->lchild;
}
}
else{
printf("%c",pcur->data);
pcur = pcur->rchild;
}
}
}

  main函数:

int main(){
TreeNode *t = (TreeNode *)malloc(sizeof(TreeNode));
TreeNode *pnew = (TreeNode *)malloc(sizeof(TreeNode));
t->data = 'A';
t->lchild = pnew;
t->lchild->data = 'B'; t->lchild->lchild = NULL;
pnew = (TreeNode *)malloc(sizeof(TreeNode));
t->lchild->rchild = pnew;
t->lchild->rchild->data = 'D';
t->lchild->rchild->lchild = NULL;
t->lchild->rchild->rchild = NULL; pnew = (TreeNode *)malloc(sizeof(TreeNode));
t->rchild = pnew;
t->rchild->data = 'C';
t->rchild->lchild = NULL;
t->rchild->rchild = NULL;
PreOrderTraverse(t);
printf("\n");
}

C前序遍历二叉树Morris Traversal算法的更多相关文章

  1. LeetCode OJ:Binary Tree Preorder Traversal(前序遍历二叉树)

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

  2. Binary Tree Inorder/Preorder Traversal 返回中序和前序/遍历二叉树的元素集合

    给定一个二叉树,以集合方式返回其中序/先序方式遍历的所有元素. 有两种方法,一种是经典的中序/先序方式的经典递归方式,另一种可以结合栈来实现非递归 Given a binary tree, retur ...

  3. 额外空间复杂度O(1) 的二叉树遍历 → Morris Traversal,你造吗?

    开心一刻 一天,有个粉丝遇到感情方面的问题,找我出出主意 粉丝:我女朋友吧,就是先天有点病,听不到人说话,也说不了话,现在我家里人又给我介绍了一个,我该怎么办 我:这个问题很难去解释,我觉得一个人活着 ...

  4. 二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离

    数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下 许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显 ...

  5. 用c语言实现前序创建二叉树(递归),分别用前序,中序,后序遍历,以及分别输出节点个数和叶子节点个数

    本人c语言小白一枚,近期在学习数据结构(c语言版),特写此随笔,做一些总结和分享,如有不当之处,请各位技术大牛斧正 首先我们用一个结构体来抽象树的结点,代码如下(这里我们存放的数据为char型,大家可 ...

  6. java编写二叉树以及前序遍历、中序遍历和后序遍历 .

    /** * 实现二叉树的创建.前序遍历.中序遍历和后序遍历 **/ package DataStructure; /** * Copyright 2014 by Ruiqin Sun * All ri ...

  7. c++实现二叉树层序、前序创建二叉树,递归非递归实现二叉树遍历

    #include <iostream> #include <cstdio> #include <stdio.h> #include <string> # ...

  8. leecode刷题(28)-- 二叉树的前序遍历

    leecode刷题(28)-- 二叉树的前序遍历 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 思路 ...

  9. Qt实现 动态化遍历二叉树(前中后层次遍历)

    binarytree.h 头文件 #ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> ...

随机推荐

  1. 时间模块time和datetime的使用

    日期和时间 一 time模块 import time 时间的表示形式: 时间戳 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现 ...

  2. 分布式结构化存储系统-HBase访问方式

    分布式结构化存储系统-HBase访问方式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. HBase提供了多种访问方式,包括HBase shell,HBase API,数据收集组件( ...

  3. HTML&CSS基础-内联和块元素

    HTML&CSS基础-内联和块元素 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.html源代码 <!DOCTYPE html> <html> ...

  4. MongoDB的关闭

    关闭 1,非后台运行时,关闭对话,或者ctrl+c 2,登录数据库执行:db.shutdownServer(); 3,带数据目录,关闭服务器,安全   mongod --shutdown --dbpa ...

  5. python抽象基类

    抽象基类 抽象基类提了一种方式,用以组织对象的层次结构,做出关于所需方法的断言,以及实现其他一些功能 要定义抽象基类,需要使用abc模块,该模块定义了一个元类(ABCMeta) 和一组装饰器(@abs ...

  6. jquery 下拉一屏

  7. 【Python学习】Python3 基本数据类型

    参考学习地址:https://www.runoob.com/python3/python3-data-type.html Python3 基本数据类型 Python 中的变量不需要声明.每个变量在使用 ...

  8. nginx添加系统服务(start|stop|restart|reload)

    nginx添加系统服务 1.编写脚本,名为nginx #vim /etc/init.d/nginx #!/bin/bash#chkconfig: - 99 20 #description: Nginx ...

  9. 项目后端 - Django配置

    Django项目创建 环境 """ 这里案例项目名叫luffy 为luffy项目创建一个虚拟环境 >: mkvirtualenv luffy "" ...

  10. 动态加载 ShellCode绕过杀软

    反病毒解决方案用于检测恶意文件,并且通常使用静态分析技术来区分二进制文件的好坏.如果是恶意文件本身包含恶意内容(ShellCode),那么依靠静态分析技术会非常有效,但如果攻击者使用轻量级的stage ...