二叉树遍历,栈实现二叉树的非递归遍历
来源:互联网 发布:linux 程序的守护进程 编辑:程序博客网 时间:2024/06/06 00:19
另见求树高 http://blog.csdn.net/Justme0/article/details/7694704
史上最简明易懂非递归遍历二叉树算法
void PreOrderTraverse_R(BiTree BT)//采用递归方式先序遍历二叉树BT{ if(BT != NULL) { printf("%c", BT->data);//输出该结点(根结点) PreOrderTraverse_R(BT->lchild); //遍历左子树 PreOrderTraverse_R(BT->rchild);//遍历右子树 }} void InOrderTraverse_R(BiTree BT)//采用递归方式中序遍历二叉树BT{ if(BT != NULL) { InOrderTraverse_R(BT->lchild); //遍历左子树 printf("%c", BT->data);//输出该结点(根结点) InOrderTraverse_R(BT->rchild);//遍历右子树 }} void PostOrderTraverse_R(BiTree BT)//采用递归方式后序遍历二叉树BT{ if(BT != NULL) { PostOrderTraverse_R(BT->lchild); //遍历左子树 PostOrderTraverse_R(BT->rchild);//遍历右子树 printf("%c", BT->data);//输出该结点(根结点) }}
相较之下,大部分流传的非递归遍历二叉树算法语言晦涩,面目可憎,虽然利用了栈数据结构来模拟递归遍历过程,但思路和表达形式上未能与递归算法对应起来,造成初学者理解上的困惑。如果能够将非递归算法和递归算法相互对应,则可大大方便初学者理解二者间的等效性。
我们知道,编译器在调用函数时会分配一个栈空间,以存储必要信息,如果该函数调用了别的函数,其栈空间会一直保留,直到该函数最后一条语句执行完毕,才会释放其栈空间。在模拟非递归算法的时候,我们需要手工分配和释放栈空间。
三种不同的遍历方式区别在于栈空间的释放时机和输出结点信息时机的不同:先序和中序遍历是在访问栈顶元素的右孩子(右子树)之前退栈,而后序遍历在访问右子树之后退栈;先序遍历是在某结点入栈时输出其信息,而中序和后序遍历是在该结点退栈时输出其信息。
无论是递归算法还是非递归算法,都遵循上述规则,二者可以一一对应。图示如下:
/********************************************************************created: 2014/05/11 23:13filename: main.cauthor: Justme0 (http://blog.csdn.net/justme0)purpose: 用栈实现二叉树的非递归中序遍历*********************************************************************/#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <assert.h>typedef struct Node Node;typedef struct Stack Stack;typedef char TElemType;typedef Node * SElemType;#pragma region 栈的定义#define STACK_INIT_SIZE 100#define STACKINCREMENT 10struct Stack { SElemType *base; SElemType *top; int stacksize;};void InitStack(Stack *pS){ (*pS).base=(SElemType*)malloc(STACK_INIT_SIZE*(sizeof(SElemType))); if(!(*pS).base) exit(-2); (*pS).top=(*pS).base; (*pS).stacksize=STACK_INIT_SIZE;}void Push(Stack *pS,SElemType T){ if((*pS).top-(*pS).base>=(*pS).stacksize) { (*pS).base=(SElemType*)realloc((*pS).base,((*pS).stacksize+STACKINCREMENT)*sizeof(SElemType)); if(!(*pS).base) exit(-2); (*pS).top=(*pS).base+(*pS).stacksize; (*pS).stacksize+=STACKINCREMENT; } *(*pS).top++=T;}int StackEmpty(Stack S){ return S.top == S.base;}int Pop(Stack (*pS),SElemType *pT){ if(StackEmpty(*pS)) return 0; *pT=*(--(*pS).top); return 1;}int GetTop(Stack S,SElemType *pT){ if(StackEmpty(S)) return 0; (*pT)=*(S.top-1); return 1;}#pragma endregion 栈的定义int Print(TElemType a){ printf("%c\n", a); return 1;}#pragma region 二叉树struct Node { TElemType data; Node *lchild; Node *rchild;};int CreatBiTree(Node **pT){//先序法创建二叉树,空格字符表示空树,每个节点一个字符 //构造二叉链表表示的二叉树 TElemType ch; scanf("%c",&ch); getchar(); if(ch==' ') { *pT = NULL; } else { if(!(*pT=(SElemType)malloc(sizeof(Node)))) exit(-2); (*pT)->data=ch; //生成根节点 CreatBiTree(&((*pT)->lchild)); //构造左子树 CreatBiTree(&((*pT)->rchild)); //构造右子树 } return 1;}//中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit。int InOrderTraverse(Node *T, int (*Visit)(TElemType e)){ Stack S; Node *p = NULL; S.base=(Node **)malloc(100*(sizeof(Node **))); 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); assert(NULL != p); if(!Visit(p->data)) return -1; Push(&S,(p->rchild)); } } return 1;}#pragma endregion 二叉树int main(void){ Node *T = NULL; freopen("cin.txt", "r", stdin); CreatBiTree(&T); InOrderTraverse(T, Print); // TODO: FreeTree(T); system("PAUSE"); return 0;}/* cin.txtABCDEGF*/转自:http://www.cnblogs.com/jjtx/p/3722553.html
0 0
- 非递归实现二叉树的遍历
- 非递归实现二叉树的遍历
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 二叉树的非递归遍历实现
- 二叉树遍历的非递归实现
- 非递归实现二叉树的遍历
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 非递归遍历二叉树的实现
- 二叉树遍历的非递归实现
- 二叉树遍历的非递归实现
- 二叉树的先中后序遍历,递归遍历,非递归遍历
- 二叉树遍历,栈实现二叉树的非递归遍历
- 用栈实现二叉树的遍历(非递归)
- 二叉树的遍历(递归实现+非递归实现)
- 二叉树的递归,非递归遍历
- 时间类
- 让年轻程序员少走弯路的14个忠告
- 关于对web.Config文件详细介绍
- hdu 5195 求最大拓扑序列 拓扑+贪心
- Linux入门:常用目录介绍
- 二叉树遍历,栈实现二叉树的非递归遍历
- IT人学习新技术的 10 个建议
- Linux入门:文件权限、用户、用户组
- 深度优先搜索 DFS(邻接矩阵表示)
- (2)设计模式:面向对象
- UML建模快速入门03 基本结构建模 CLASS
- Linux入门:文本编辑器(nano)
- P51题13题
- cracking the interview