二叉树递归遍历可谓是学过数据结构的同仁都能想一下就能写出来,但在应聘过程我们常常遇到的是写出一个二叉树非递归遍历函数,接着上篇文章写二叉树的非递归遍历,先难后易,一步一步的来.

先上代码:

#include "binarytree.h"
#include <stack>
#include <queue>#ifndef RECU
#warning("RECU is not defined")/***前序遍历(根左右)**1、当前节点为非空,访问当前节点,压栈其右子节点,考虑其左子节点*2、当前节点为NULL,出栈**@param t to visit*@param visit point to a func*/
void pre_order(link t, void (*visit)(link))
{std::stack<link> myStack;while( t || !myStack.empty() ) {if ( t ) {visit(t);myStack.push(t->rchild);t = t->lchild;} else {t = myStack.top();myStack.pop();}}
}/***中序序遍历(左根右)**1、当前节点为非空,在访问当前节点前要先访问其左子节点,*   压栈当前节点,判断其左子结点,一直压栈左子节点*2、当前节点为NULL,出栈访问,其左子结点比当前节点出栈访问早,*   此时当前节点是其右节点的父节点的角色,考虑其右节点**在遍历过程中角色转换很重要**@param t to visit*@param visit point to a func*/
void in_order(link t, void (*visit)(link))
{std::stack<link> myStack;while( t || !myStack.empty() ) {if ( t ) {myStack.push(t);t = t->lchild;} else {t = myStack.top();myStack.pop();visit(t);t = t->rchild;}}
}/***后序遍历(左右根)**1、由于在访问当前树的根结点时,应先访问其左、右子树,因而先将根结点入栈,*   接着将右子树也入栈,然后考虑左子树,重复这一过程直到某一左子树为空*2、如果当前考虑的子树为空,*   1.若栈顶不为空,说明第二栈顶对应的树的右子树未处理,*   则弹出栈顶,下次循环处理,并将一空指针入栈以表示其另一子树已做处理;*   2.若栈顶也为空树,说明第二栈顶对应的树的左右子树或者为空,或者均已做处理,*   直接访问第二栈顶的结点,访问完结点后,若栈仍为非空,说明整棵树尚未遍历完,*   则弹出栈顶,并入栈一空指针表示第二栈顶的子树之一已被处理。**@param t to visit*@param visit point to a func*/
void post_order(link t, void (*visit)(link))
{std::stack<link> myStack;while( 1 ) {if ( t ) {myStack.push(t);myStack.push(t->rchild);t = t->lchild;} else {t = myStack.top();myStack.pop();if (!t) {t = myStack.top();myStack.pop();visit(t);if (myStack.empty())break;t = myStack.top();myStack.pop();}myStack.push(NULL);}}
}
#endif/***层遍历**@param t to visit*@param visit point to a func*/
void level_order(link t, void (*visit)(link))
{std::queue<link> myQueue;if (t) {myQueue.push(t);while( !myQueue.empty() ) {link tmp = myQueue.front();myQueue.pop();visit(tmp);if (tmp->lchild != NULL)myQueue.push(tmp->lchild);if (tmp->rchild != NULL)myQueue.push(tmp->rchild);}}
}

在非递归遍历函数中我们用到了堆栈和队列,为几种注意力到一件事上,在堆栈和队列的实现上,本人第一时间想到的是拿来主义,到github去下载别人的源码来实现.
下载了一个版本都没达到想要的效果,于是乎目标转移到C++ STL上,最终版本是在C源文件上实现二叉树的递归函数,在CPP文件中实现二叉树的非递归函数.所以在make的时候定义一个变量recu=y来应用递归函数,其他情况则应用非递归函数。

由于C与C++公用,那么咱们的头文件就要动点手脚了,否就会有意外情况出现

/* binarytree.h */
#ifndef BINARYTREE_H
#define BINARYTREE_H#ifdef __cplusplus
extern "C" {
#endiftypedef struct node *link;
/***节点中的数据类型重定义*/
typedef unsigned char TElemType;struct node { TElemType item; link lchild, rchild;
};link init(TElemType VLR[], TElemType LVR[], int n);void pre_order(link t, void (*visit)(link));
void in_order(link t, void (*visit)(link));
void post_order(link t, void (*visit)(link));
#ifndef RECU
void level_order(link t, void (*visit)(link));
#endifvoid pprint(link t);
int count(link t);
int depth(link t);
void destroy(link t);/**
*http://www.cnblogs.com/bizhu/archive/2012/08/19/2646328.html 算法图解
*
*二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树,
*它或者是一棵空树;或者是具有下列性质的二叉树:
*(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
*(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
*(3)左、右子树也分别为二叉排序树;
*(4)排序二叉树的中序遍历结果是从小到大排列的.
*
*二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,为O(log n)。
*二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。
*
*搜索,插入,删除的复杂度等于树高,期望O(log n),最坏O(n)(数列有序,树退化成线性表)
*改进版的二叉查找树可以使树高为O(logn),如SBT,AVL,红黑树等.
*
*程序来源于Linux C编程一站式学习
*/
link bstSearch(link t, TElemType key);
link bstInsert(link t, TElemType key);
link bstDelete(link t, TElemType key);/***http://baike.baidu.com/view/593144.htm?fr=aladdin*平衡二叉树*/
#ifdef __cplusplus
}
#endif
#endif

对于__cplusplus这个玩意纠结了很久,模模糊糊知道他是干什么用的,具体放在什么地方纠结了好一阵子,最后一狠心自己动手编译试一下,暂且只定义响应的空函数,看看编译连接是否OK,出人意料万事OK。由此看来动手能力决定一切啊。

对Makefile文件改动如下:

#if you want to use recursive func,please make recu=y
ifeq (y, $(recu))CFLAGS += -DRECU
endififeq (y, $(debug))CFLAGS += -g
endifCC = gcc
CPLUS = g++
CFLAGS += -Wall
TARGET = treeall:$(TARGET).c.o:$(CC) $(CFLAGS) -o $@ -c $<.cpp.o:$(CPLUS) $(CFLAGS) -o $@ -c $<$(TARGET): non_binarytree.o binarytree.o main.o$(CPLUS) $(CFLAGS) -o $@ $^test:@./tree > result.txt && python result.py | tree -b2.PHONY: all clean
clean:$(RM) $(TARGET) *.o

在改动Makefile的工程中遇到了两个问题:
1、本人认为主程序是C程序,所以在连接的时候用的是gcc,随后爆出"undefinedreference to '__gxx_personality_v0' " 错误。
重来没有遇到过,只有问度娘,得出的结果如下:
对于 C++ 程序,编译的时候用 gcc 或者 g++ 都可以。但是在进行连接的时候最好用 g++,因为用 g++ 会自动进行 C++ 标准库的连接;用 gcc 连接 C++ 程序也可以,但是需要人为指定连接 C++ 标准库,否则就会出现 undefined reference to `__gxx_personality_v/0' 之类的错误。可见-lstdc++ 所对应的是标准C++库
2、当定义RECU这个宏后,发现函数重复定义,排查了一下函数定义,在C文件中函数定义用"#dedef RECU  ****  #endif",在C++文件中"#ifndef RECU   ...... #endif"隔开了呀,用"#warning()"添加编译过程中的打印信息,定义RECU与否总会编译到非递归函数,我去,奇了怪了。
在仔细排查,发现编译C++文件时没有定义RECU。
Makefile内容改动如下:

%.o:%.c$(CC) $(CFLAGS) -o $@ -c $<%.o:%.cpp$(CPLUS) $(CFLAGS) -o $@ -c $<
================改成了================
.c.o:$(CC) $(CFLAGS) -o $@ -c $<.cpp.o:$(CPLUS) $(CFLAGS) -o $@ -c $<

问题是解决了,但这两种写法有什么不同还是没有个所以然
======================================================================

脚本是自动化的神器,输出的序列手动用tree工具转换成图形确实麻烦,于是乎想到之前有个博友测试计算公式的效率时用到python:
1、python输出计算所需要的参数,print函数就OK
2、测试程序用scanf判断输入的参数个数是否OK
3、实现就是python程序输出的结构通过管道送到测试程序
自动化测试用这个方法可能凑效

写个脚本一行行的输出测试程序的结果:

fp = open('result.txt')
for line in fp.readlines():print(line)

Makefile添加如下语句:

test:@./tree > result.txt && python result.py | tree -b2

测试只需make test就OK

推荐阅读:https://blog.csdn.net/LLZK_/article/details/52829525

二叉树学习之非递归遍历相关推荐

  1. 二叉树的前序非递归遍历

    二叉树的前序非递归遍历 前面学习过二叉树的前序遍历,使用递归的方式.简单回顾一下: Status PerOrder(BiTree T) {//前序遍历二叉树if (T != NULL) {Visit( ...

  2. 对于二叉树三种非递归遍历方式的理解

    利用栈实现二叉树的先序,中序,后序遍历的非递归操作 栈是一种先进后出的数据结构,其本质应是记录作用,支撑回溯(即按原路线返回):因此,基于其的二叉树遍历操作深刻的体现了其特性: 若后续的输入和其前面的 ...

  3. 二叉树中序非递归遍历

    递归是程序设计中强有力的工具.递归函数结构清晰,使程序易读.但递归函数也有不可克服的弱点,时间.空间效率较低,运行代价较高,所以在实际使用中,常希望使用它的迭代版本.为了实现非递归遍历算法,需要一个堆 ...

  4. 二叉树 中序非递归遍历算法 c++

    二叉树的中序非递归算法,详见下 首先,二叉树结点定义 typedef struct BiTNode//二叉树结点结构 {string data;struct BiTNode *lchild,*rchi ...

  5. 二叉树 2.0 -- 非递归遍历

    二叉树递归遍历存在的问题 如果我们的二叉树只有左子树,而且树的高度还很深的时候,这个时候递归调用遍历的时候,栈帧空间开辟的较大,很可能造成栈溢出.但是我们一个程序中,为堆分配的空间要比栈大的多,这个时 ...

  6. 二叉树的先序,中序,后序,层次的递归及非递归遍历

    昨天写数据结构关于二叉树的几种顺序的递归及非递归遍历的程序,后续遍历有点难.现在把程序给大家参考一下,有些思路参考自:http://www.cnblogs.com/dolphin0520/archiv ...

  7. 二叉树的后序非递归遍历(巧妙思想)

    大家都知道二叉树的前序非递归遍历非常好写: //二叉树的结构 public class TreeNode {TreeNode left;TreeNode right;int val;TreeNode( ...

  8. 数据结构专题 | 先序非递归遍历二叉树

    先序非递归遍历二叉树,主要是利用了栈的先进后出原理,用一个栈即可实现该算法,下面我们一起来看一下如何来实现吧 目录 先序建立二叉树 先序递归遍历二叉树 先序非递归遍历二叉树 先序建立二叉树 在进行先序 ...

  9. 冰冰学习笔记:二叉树的进阶OJ题与非递归遍历

    欢迎各位大佬光临本文章!!! 还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正. 本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬.帅哥.美女点点支 ...

最新文章

  1. 观看马云网商大会视频的一些感想.
  2. java链式结构_(Java)单链表Java语言链式结构实现(数据结构四)
  3. 。。。剑指Offer之——用两个栈实现队列。。。
  4. python基础入门(Peak带你学python)
  5. Perl,Python,Ruby,Javascript 四种脚本语言比较
  6. 无心剑中译丁尼生《磨坊主千金》
  7. 人脸关键点: Wing Loss for Robust Facial Landmark Localisation with Convolutional Neural Networks
  8. SSH集成项目,使用注解方式,竟然还有这样的问题!!
  9. python之t分布
  10. julia安装源_在Linux系统中下载与安装Julia 1.0.1
  11. 【2015DTCC】专访永洪科技CEO:商业智能搬运大数据之谜
  12. 局域网内ping不通另外一台电脑_疫情期间宅家一台电脑如何做计算机网络实验...
  13. 思科2960交换机密码破解
  14. Java设计模式——行为型模式之观察者模式
  15. Java基础之MySQL数据库与JDBC
  16. Head First Design Mode(2)-设计模式入门(策略模式)
  17. Android魅族等手机下拉刷新有留白(下拉悬停)
  18. 东南亚电商发展迅猛,中国卖家“钱”途光明
  19. LabVIEW编程LabVIEW开发 控制双轴倾角传感器BWH526例程与相关资料
  20. 教授专栏54 | 香港科大商学院绿色金融研究小组:借鉴外地经验,培育绿色金融人才...

热门文章

  1. Linux的实际操作:文件和文件夹的权限解读
  2. flask get 参数_用它 5 分钟以后,我放弃用了四年的 Flask
  3. java jar 没有主清单属性_Spring Boot jar中没有主清单属性的解决方法
  4. centos7开启vnc服务_阿里云CentOS 7搭建VNC远程桌面服务步骤方法
  5. 云教版认识计算机说课,【教学设计】第1册第1课《认识电脑交朋友》
  6. 项目日报模板_第一届全国技能大赛现场直击:混凝土建筑项目全场最“高”
  7. python正则表达式生成器_Python学习之路-装饰器生成器正则表达式
  8. php curl header_PHP中的yield与协程(二十一节)
  9. 【LeetCode笔记】剑指 Offer 56 . 数组中数字出现的次数(Java、位运算)
  10. python允许无止境的循环_ParisGabriel:Python无止境 day03