如下这棵二叉树的先序遍历结果为:ABDEFPC
#include <stdio.h> #include <malloc.h>
//#define ElemType char typedef char ElemType;
typedef struct BiTNode{ ElemType data; struct BiTNode *lchild, *rchild; }BiTNode, *BiTree;
#define MAX 10000 typedef struct{ BiTree data[MAX]; int top; }SeqStack;
|
对上图的二叉树,按照代码的思路说明如何用非递归的方式遍历一棵二叉树:
|
void pre_order_nonrecursive(BiTree T) { SeqStack s; s.top = -1;
BiTree tmp = T;
while(tmp){// while1开始 while(tmp){// while2 开始 printf("%c",tmp->data);
if(tmp->rchild){ if(s.top == MAX-1){ exit(0); }else{ s.data[++s.top] = tmp->rchild; } } tmp = tmp->lchild; }// while2结束
if(s.top != -1){ tmp = s.data[s.top--]; }
}// while1结束
printf("\n");
}
tmp结点的来源: 如果tmp的左孩子不为空,就把这个左孩子更新给tmp; 否则, 如果栈不为空,就把栈顶元素弹出并更新给tmp; 如果栈为空,说明这棵二叉树遍历完毕 |
T = A tmp = T =A 打印A A的右孩子存在为结点C,不为空 s.stop = -1<10000,此时栈为空,栈不满 把C(的地址)入栈,同时栈顶指针stop加1变为0
tmp=A的左孩子=B 打印B B的右孩子存在为结点P,不为空 s.stop = 0<10000,此时栈不满 把P(的地址)入栈同时栈顶指针stop加1变为1
tmp=B的左孩子=D 打印D D的右孩子存在为结点E,不为空 s.stop = 1<10000,此时栈不满 把E(的地址)入栈同时栈顶指针stop加1变为2
tmp=D的左孩子=空 s.stop = 2>-1,此时栈不空 从栈中弹出栈顶元素E给tmp, 同时栈顶指针stop减1变为1
tmp=E 打印E E没有右孩子,不进行入栈操作
tmp=E的左孩子=F 打印F F没有右孩子,不进行入栈操作
tmp=F的左孩子=空 s.stop = 1>-1,此时栈不空 从栈中弹出栈顶元素P给tmp, 同时栈顶指针stop减1变为0
tmp=P 打印P P没有右孩子,不进行入栈操作
tmp=P的左孩子=空 s.stop = 0>-1,此时栈不空 从栈中弹出栈顶元素C给tmp, 同时栈顶指针stop减1变为-1
tmp=C 打印C C没有右孩子,不进行入栈操作
tmp=C的左孩子=空 s.stop = -1,栈空,不能进行弹栈操作
Tmp=空
先序遍历结束: 打印结果为ABDEFPC |
#include <stdio.h>
#include <malloc.h>
//#define ElemType char
typedef char ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
#define MAX 10000
typedef struct{
BiTree data[MAX];
int top;
}SeqStack;
void pre_order_nonrecursive(BiTree T)
{
SeqStack s;
s.top = -1;
BiTree tmp = T;
while(tmp){
while(tmp){
printf("%c",tmp->data);
if(tmp->rchild){
if(s.top == MAX-1){
exit(0);
}else{
s.data[++s.top] = tmp->rchild;
}
}
tmp = tmp->lchild;
}
if(s.top != -1){
tmp = s.data[s.top--];
}
}
printf("\n");
}
二叉树的非递归先序遍历 |
|
#define MAX 10000 |
宏定义是简单的符号代换,这里MAX符号的含义是栈中最多存放10000个结点的地址 |
typedef struct{ |
自定义一个结构体类型用于 栈操作 |
BiTree data[MAX]; |
定义一个数组类型的变量,用于存储栈中的元素 作为先序遍历,栈中存放的都是树中某个结点的右孩子 |
int top; |
定义栈的栈顶指针top,它始终指向栈顶元素 |
}SeqStack; |
|
void pre_order_nonrecursive(BiTree T) |
参数T:即将被遍历的树的 树根地址 |
{ |
|
SeqStack s; |
声明栈 |
s.top = -1; |
初始化栈的栈顶指针为-1,因为数组的第一个元素的下标是0,而此时作为栈的这个数组里面没有存放数据 |
|
|
BiTree tmp = T; |
声明一个结点指针类型的变量tmp用于遍历树,并初始化为树根地址 |
|
|
while(tmp){ |
外层while循环: tmp结点一开始是根结点, 之后就是每一个左枝的最后一个右孩子, 也是从栈中弹出的栈顶元素 |
while(tmp){ |
内层while循环:遍历穷尽结点tmp的左枝 |
printf("%c",tmp->data); |
先序遍历:根左右,所以拿到一个不为空的结点的时候,应首先打印这个结点的数据 |
|
|
if(tmp->rchild){ |
如果当前这个结点有右孩子 |
if(s.top == MAX-1){ |
并且 如果栈满 |
exit(0); |
栈的容量不足以支持后序的先序遍历操作,立即退出程序,不继续再做任何操作 |
}else{ |
并且 如果栈不满 |
s.data[++s.top] = tmp->rchild; |
把当前结点的右孩子的地址存到栈中,因为它以及它的子树还没有被遍历;同时作为数据进栈的配套栈操作,把栈指针加一 |
} |
|
} |
|
tmp = tmp->lchild; |
为了遍历穷尽结点tmp的左枝,把tmp更新为当前结点的左孩子地址 |
} |
|
|
|
if(s.top != -1){ |
此时tmp结点的左枝遍历穷尽, 如果栈不为空,需要弹出栈顶元素,并把tmp更新为这个元素, 这个栈顶元素是左枝上的最后一个有右孩子的结点的右孩子 |
tmp = s.data[s.top--]; |
|
} |
|
}
printf("\n");
|
|
} |