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

#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. 安装sqlite3

    说明 当前操作在root用户下执行 1.安装编译工具 yum -y groupinstall "Development tools" yum -y install zlib-dev ...

  2. lvm快照备份mysql

    快照备份原理(从其他博客看的): 原理:通过lvm快照给lvm真身拍个照片,当lvm真身发送改变时,lvm快照把lvm真身改变之前的内容存放在快照上,这样在lvm快照有效的这段时间内,我们看到的lvm ...

  3. dt开发之-自定义函数获取分类名称

    需要在api/extend.func.php 文件中加入的函数 获取分类名称 cat_name($catid) 传入分类id function cat_name($catid) { global $d ...

  4. 任何人都适合的常用Chrome插件(工欲善其事必先利其器)

    1.划词翻译 介绍链接:http://t.cn/RqpoGU4 下载地址: Chrome 应用商店(请翻墙). 下载 .crx 安装包手动安装 功能如下: - 支持几乎所有语言的翻译与阅读,并且同时支 ...

  5. vue中超简单的方法实现点击一个按钮出现弹框,点击弹框外关闭弹框

    效果图展示: View层 <template> <div> <div class="mask" v-if="showModal" ...

  6. Vue 组件生命周期钩子

    Vue 组件生命周期钩子 # 1)一个组件从创建到销毁的整个过程,就称之为组件的生命周期 # 2)在组件创建到销毁的过程中,会出现众多关键的时间节点, 如: 组件要创建了.组件创建完毕了.组件数据渲染 ...

  7. 【小技巧】O(1)快速乘

    问题:求 \(a\times b\bmod p\),\(a,b,p\) 在 long long 范围内. 在 CRT 等算法中应用广泛. 为了处理模数在 int 范围外的情况,就是两数相乘可能会爆 l ...

  8. C#指针使用demo

    #region 使用指针检索数据值 //class program //{ // // 1.项目属性勾选“允许不安全代码” // // 2.使用unsafe 修饰符 // // 这里是将整个Main方 ...

  9. LightOJ - 1170 - Counting Perfect BST(卡特兰数)

    链接: https://vjudge.net/problem/LightOJ-1170 题意: BST is the acronym for Binary Search Tree. A BST is ...

  10. 使用自签CA,Server,client证书和双向认证

    服务端代码 package main import ( "crypto/tls" "crypto/x509" "google.golang.org/g ...