一.简述

  二叉树的遍历主要是先序、中序、后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些。二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具!

  此外,非递归所用的栈及相关操作是第三章实现的,但数据类型做了更改。

  二.头文件

 //3_1.h
/**
author:zhaoyu
email:zhaoyu1995.com@gmail.com
date:2016-6-7
note:realize my textbook <<数据结构(C语言版)>>
*/
//Page 46
#ifndef _3_1_FOR_CHAPTER6_H_
#define _3_1_FOR_CHAPTER6_H_
#include <cstdio>
#include <cstdlib>
#include "head.h"
/**
My Code
*/
#define SElemType BiTree
//----栈的顺序存储表示----
#define STACK_INIT_SIZE 100//存储空间的初始分配值
#define STACKINCREMENT 10//存储空间分配增量
typedef struct{
SElemType *base;//在栈构造之前和销毁之后,base 值为 NULL
SElemType *top;//栈顶指针
int stacksize;//当前已分配的存储空间,以元素为单位
}SqStack;
//----基本操作的函数原型说明及部分实现----
Status InitStack(SqStack &S)
{
//构造一个空栈 S
S.base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if (!S.base)
{
exit(OVERFLOW);
}
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}//InitStack Status StackEmpty(SqStack S)
{
//若 S 为空栈, 则返回 TRUE, 否则返回 FALSE
if (S.base == S.top)
{
return TRUE;
}
else
{
return FALSE;
}
} Status GetTop(SqStack S, SElemType &e)
{
//若栈不空,则用 e 返回 S 的栈顶元素,并返回 OK;
//否则返回ERROR
if (S.top == S.base)
{
return ERROR;
}
e = *(S.top - );
return OK;
}//GetTop
Status Push(SqStack &S, SElemType e)
{
//插入元素 e 为新的栈顶元素
if (S.top - S.base >= S.stacksize)
{//栈满,追加存储空间
S.base = (SElemType *)realloc(S.base,
(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if (!S.base)
{
exit(OVERFLOW);
}
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
return OK;
}//Push
Status Pop(SqStack &S, SElemType &e)
{
//若栈不空,则删除 S 的栈顶元素,用 e 返回其
//值,并返回OK;否则返回ERROR
if (S.top == S.base)
{
return ERROR;
}
e = *--S.top;
return OK;
}//Pop
#endif

3_1_for_chapter6.h

 //6_3_part1.h
/**
author:zhaoyu
date:2016-6-18
*/
#include "head.h"
#define TElemType char
//----二叉树的二叉链表表示----
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild, *rchild;
}*BiTree;
/**
algorithm 6.4
*/
Status CreateBiTree(BiTree &T)
{//按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树
//构造二叉链表表示的二叉树
char ch;
scanf("%c", &ch);
if (' ' == ch)
{
T = NULL;
}
else
{
if (!(T = (BiTree)malloc(sizeof(BiTNode))))
{
exit(OVERFLOW);
}
T->data = ch;//生成根结点
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return OK;
}
Status Visit(TElemType e)
{
printf("%c", e);
return OK;
}
/**
algorithm 6.1
*/
Status RecursionPreOrderTraverse(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//先序遍历二叉树 T 的递归算法
if (T)
{
if (Visit(T->data))
{
if (RecursionPreOrderTraverse(T->lchild, Visit))
{
if (RecursionPreOrderTraverse(T->rchild, Visit))
{
return OK;
}
}
}
return ERROR;//这一行由于 Visit 函数只 return OK,貌似没什么用
}
else
{
return OK;
}
} Status RecursionInOrderTraverse(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//中序遍历二叉树 T 的递归算法
if (T)
{
if (RecursionInOrderTraverse(T->lchild, Visit))
{
if (Visit(T->data))
{
if (RecursionInOrderTraverse(T->rchild, Visit))
{
return OK;
}
}
}
return ERROR;
}
else
{
return OK;//注意是 return OK;
}
}
Status RecursionPostOrderTraverse(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//后序遍历二叉树 T 的递归算法
if (T)
{
if (RecursionPostOrderTraverse(T->lchild, Visit))
{
if (RecursionPostOrderTraverse(T->rchild, Visit))
{
if (Visit(T->data))
{
return OK;
}
}
}
return ERROR;
}
else
{
return OK;
}
} #include "3_1_for_chapter6.h"
Status UnRecursionPreOrderTraverse(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//先序遍历二叉树 T 的递归算法
SqStack S;
BiTree p = T;
InitStack(S);
while (p || !StackEmpty(S))
{
if (p)
{
if (!Visit(p->data))
{
return ERROR;
}
Push(S, p);
p = p->lchild;//根指针进栈遍历做子树
}
else
{//根指针退栈,访问根结点,遍历右子树
Pop(S, p);
p = p->rchild;
}
}
return OK;
}
/**
algorithm
*/
Status UnRecursionInOrderTraverse_1(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//中序遍历二叉树 T 的递归算法
BiTree p = NULL;
SqStack S;
InitStack(S);
Push(S, T);//跟指针进栈
while (!StackEmpty(S))
{
while (GetTop(S, p) && p)
{
Push(S, p->lchild);//从左走到尽头
}
Pop(S, p);//空指针退栈
if (!StackEmpty(S))
{
Pop(S, p);
if (!Visit(p->data))
{
return ERROR;
}
Push(S, p->rchild);
}
}
return OK;
}
Status UnRecursionInOrderTraverse_2(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//中序遍历二叉树 T 的递归算法
SqStack S;
BiTree p = T;
InitStack(S);
while (p || !StackEmpty(S))
{
if (p)
{
Push(S, p);
p = p->lchild;//根指针进栈遍历做子树
}
else
{//根指针退栈,访问根结点,遍历右子树
Pop(S, p);
if (!Visit(p->data))
{
return ERROR;
}
p = p->rchild;
}
}
return OK;
}
Status UnRecursionPostOrderTraverse(BiTree T, Status (* Visit)(TElemType e))
{//采用二叉链表存储结构,Visit是对数据元素操作的应用函数
//后序遍历二叉树 T 的递归算法
//稍难一点
SqStack S;
BiTree p = T, pre = NULL;
InitStack(S);
Push(S, p);
while (!StackEmpty(S))
{
if (GetTop(S,p) && p->lchild && pre!=p->lchild && !(p->rchild && pre == p->rchild))
{
Push(S, p->lchild);
}
else if (p->rchild && pre!=p->rchild)
{
Push(S, p->rchild);
}
else
{
Pop(S, p);
if (!Visit(p->data))
{
return ERROR;
}
pre = p;
}
}
return OK;
}

6_3_part1.h

  三.CPP文件

 #include "6_3_part1.h"
int main(int argc, char const *argv[])
{
BiTree T = NULL;
CreateBiTree(T);
printf("RecursionPreOrderTraverse\t");
RecursionPreOrderTraverse(T, Visit);
printf("\n");
printf("\n");
printf("\n"); printf("RecursionInOrderTraverse\t");
RecursionInOrderTraverse(T, Visit);
printf("\n");
printf("\n");
printf("\n"); printf("RecursionPostOrderTraverse\t");
RecursionPostOrderTraverse(T, Visit);
printf("\n");
printf("\n");
printf("\n"); printf("UnRecursionPreOrderTraverse\t");
UnRecursionPreOrderTraverse(T, Visit);
printf("\n");
printf("\n");
printf("\n"); printf("UnRecursionInOrderTraverse_1\t");
UnRecursionInOrderTraverse_1(T, Visit);
printf("\n");
printf("\n");
printf("\n"); printf("UnRecursionInOrderTraverse_2\t");
UnRecursionInOrderTraverse_2(T, Visit);
printf("\n");
printf("\n");
printf("\n"); printf("UnRecursionPostOrderTraverse\t");
UnRecursionPostOrderTraverse(T, Visit);
printf("\n");
printf("\n");
printf("\n");
return ;
}

6_3_part1.cpp

  四.测试

  测试用例(书的129页图6.9):

  

  各种遍历表示

  

数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树的更多相关文章

  1. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  2. 数据结构算法C语言实现(十)--- 3.3栈与递归的实现

    一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...

  3. 数据结构算法C语言实现(十九)--- 5.5&5.6&5.7广义表

    一.简述 传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一 ...

  4. 数据结构算法C语言实现(十四)--- 4.1&4.2串的类型定义、表示及实现

    一.简述 [暂无] 二.头文件 //4_2_part1.h /** author:zhaoyu */ //2016-6-10 //----串的定长顺序存储表示---- #include "h ...

  5. 数据结构算法C语言实现(三十二)--- 9.1静态查找表

    一.简述 静态查找表又分为顺序表.有序表.静态树表和索引表.以下只是算法的简单实现及测试,不涉及性能分析. 二.头文件 /** author:zhaoyu date:2016-7-12 */ #inc ...

  6. 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

    一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...

  7. 数据结构算法C语言实现(二十七)--- 7.2图的遍历

    一.简述 栈与队列,DFS与BFS.仅以连接表为例实现. 二.头文件 BFS要用到的头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@g ...

  8. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  9. 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加

    一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...

随机推荐

  1. UML:类图复习-鸡生蛋,蛋生鸡

    这是前一阵<高级软件工程>课堂上,老师随堂出的一道讨论题,随手贴在这里: ps: 今天是520,正好聊一些OoXx,关于爱的扯淡话题:) 题目:“鸡生蛋,蛋孵鸡”,世间万物生生不息,如何用 ...

  2. eclipse: workspace出错导致无法启用的解决

    通常我们会在eclipse中创建多个workspace,比如一个用于学习,一个用于工作... ,因为种种原因,时不时会发现eclipse切换workspace后启动失败,提示让你去看workspace ...

  3. java之yield(),sleep(),wait()区别详解

    1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁.也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据.注意该方 ...

  4. 塔吊力矩限制器,塔吊黑匣子,塔吊电脑,tower crane

    塔机力矩限制器,tower crane 适用于各种类型的固定臂塔机和可变臂塔机 塔机力矩限制器是塔式起重机机械的安全保护装置,本产品采用32位高性能微处理器为硬件平台,软件算法采用国内最先进的三滑轮取 ...

  5. 使用pngquant来压缩png资源缩小apk

    最近发现了一个叫做pngquant的工具,可以有效的压缩资源文件中的png文件,从而减小发布的apk的大小.我发现这个工具有两个特点: 1. 真无损,压缩后重新运行了我的app发现是没有任何区别的 2 ...

  6. 基于Laravel+Swoole开发智能家居后端

    基于Laravel+Swoole开发智能家居后端 在上一篇<Laravel如何优雅的使用Swoole>中我已经大概谈到了Laravel结合Swoole的用法. 今天,我参与的智能家居项目基 ...

  7. APP架子迁移指南(三)

    在完成上一篇之后,断断续续的开始重构我的Android项目代码,现在终于完成了.在重构期间又仔细阅读了一些开源项目的源码及文章,并询问了一些大神思路,按照理解自己完成了MVP结构的重构,与google ...

  8. 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 10(排行榜界面&界面管理)

    继上一次介绍了<神奇的六边形>的完整游戏开发流程后(可点击这里查看),这次将为大家介绍另外一款魔性游戏<跳跃的方块>的完整开发流程. (点击图片可进入游戏体验) 因内容太多,为 ...

  9. SQL Server使用游标或临时表遍历数据

    方法一:使用游标(此方法适用所有情况,对标结构没有特殊要求.) declare @ProductName nvarchar() declare pcurr cursor for select Prod ...

  10. 【转】赶集网mysql开发36军规

    原文链接:https://segmentfault.com/a/1190000004711147 写在前面的话:总是在灾难发生后,才想起容灾的重要性:总是在吃过亏后,才记得曾经有人提醒过. (一)核心 ...