如下这棵二叉树的先序遍历结果为:ABDEFPC
![](https://i-blog.csdnimg.cn/blog_migrate/7a239b08ec91c10a963a809636d1da54.png)
#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");
|
|
} |