6.4二叉树的遍历-非递归
一.了解递归
了解了递归中操作系统做了什么,非递归的实现也就不难理解了。
在系统调用函数时,需完成三件事:
(1)将实参、返回地址传递给被调用函数保存。
(2)为被调用函数等分配存储区。
(3)控制转移到被调用函数入口。
被调用函数返回主调函数,系统也需完成三件事:
(1)保存被调函数返回值。
(2)释放被调函数数据区。
(3)依照被调函数保存的地址控制转移到主调函数
二.二叉树遍历的非递归实现
(0)二叉树的创建 见6.1二叉树的创建
二叉树的递归遍历 见6.2二叉树的遍历
(1)用栈模拟递归,二叉树的非递归遍历依然分三种。
A.LDR中序遍历
void inorder(Stack &S, BiTree &t)
{
BiTree p = t;
while( p || S.top != S.bottom)
{
if(p)
{
push(S,p);
p = p -> lchild;
}
else
{
pop(S,p);
printf("%c ",p -> data);
p = p -> rchild;
}
}
}
B.DLR先序遍历
void preorder(Stack &S, BiTree &t)
{
BiTree p = t;
while( p || S.top != S.bottom)
{
if(p)
{
printf("%c ",p -> data);
push(S,p);
p = p -> lchild;
}
else
{
pop(S,p);
p = p -> rchild;
}
}
}
C.LRD后序遍历(较复杂)
<span style="font-size:18px;">void postorder(Stack &S, BiTree &t)
{
BiTree p = t;
BiTree cur;
BiTree pre = p;
push(S,p);
while(S.top != S.bottom)
{
cur = *(S.top-1);
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild || pre==cur->rchild)))
{
printf("%c ",cur -> data); //如果当前结点没有孩子结点或者孩子节点都已被访问过
pop(S,cur);
pre = cur;
}
else
{
if(cur->rchild != NULL)
push(S,cur -> rchild);
if(cur->lchild != NULL)
push(S,cur -> lchild);
}
}
}</span>
三.完整程序源代码
/* 样例输入:abc##de#g##f### */
#include<iostream>
#include<stdlib.h>
#define len (sizeof(BiNode))
#define OK 1
typedef struct bintree
{
struct bintree *lchild, *rchild;
char data;
} BiNode, *BiTree;
BiTree t;//头结点指针
typedef struct stack
{
BiTree *top;
BiTree *bottom;
int stacksize;
}Stack;
Stack S;
int bintree_creat(BiTree &q);
void InitStack(Stack &S);
void visit(BiTree t);
void preorder(Stack &S, BiTree &t);
void inorder(Stack &S, BiTree &t);
void postorder(Stack &S, BiTree &t);
void push(Stack &S, BiTree &p);
void pop(Stack &S, BiTree &p);
int main()
{
printf("input node data :");
bintree_creat(t);
InitStack(S);
visit(t);
return 0;
}
int bintree_creat(BiTree &q)
{
char n;
n = getchar();
if(n == '#')
q = NULL;
else
{
q = (BiTree )malloc(len);
q->data = n;
bintree_creat(q -> lchild);
bintree_creat(q -> rchild);
}
return OK;
}
void InitStack(Stack &S)
{
printf("input stacksize :");
scanf("%d",&S.stacksize);
S.bottom = S.top = (BiTree *)malloc(S.stacksize*sizeof(BiTree ));
}
void visit(BiTree t)
{
int i;
while(1)
{
printf("\n\ninput 1 : preorder the tree !\ninput 2 : inorder the tree !\ninput 3 : postorder the tree !\ninput 0 to exit\n\n");
scanf("%d",&i);
switch (i)
{
case 1 :preorder(S,t); break;
case 2 :inorder(S,t); break;
case 3 :postorder(S,t); break;
case 0 :exit(0);
default:printf("input error !");break;
}
}
}
void preorder(Stack &S, BiTree &t)
{
BiTree p = t;
while( p || S.top != S.bottom)
{
if(p)
{
printf("%c ",p -> data);
push(S,p);
p = p -> lchild;
}
else
{
pop(S,p);
p = p -> rchild;
}
}
}
void inorder(Stack &S, BiTree &t)
{
BiTree p = t;
while( p || S.top != S.bottom)
{
if(p)
{
push(S,p);
p = p -> lchild;
}
else
{
pop(S,p);
printf("%c ",p -> data);
p = p -> rchild;
}
}
}
void postorder(Stack &S, BiTree &t)
{
BiTree p = t;
BiTree cur;
BiTree pre = p;
push(S,p);
while(S.top != S.bottom)
{
cur = *(S.top-1);
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild || pre==cur->rchild)))
{
printf("%c ",cur -> data); //如果当前结点没有孩子结点或者孩子节点都已被访问过
pop(S,cur);
pre = cur;
}
else
{
if(cur->rchild != NULL)
push(S,cur -> rchild);
if(cur->lchild != NULL)
push(S,cur -> lchild);
}
}
}
void push(Stack &S, BiTree &p)
{
*S.top++ = p;
}
void pop(Stack &S, BiTree &p)
{
p = * --S.top;
}
参考:http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html