二叉树的 非递归 中序遍历 |
|
//#define ElemType char |
|
typedef char ElemType; |
结点中存放的数据的类型的定义 |
|
|
typedef struct BiTNode{ |
树结点的定义 |
ElemType data; |
|
struct BiTNode *lchild, *rchild; |
|
}BiTNode, *BiTree; |
BiTNode是一个结构体变量; BiTree是一个结构体变量的地址; BiTree = BiTNode * |
|
|
#define MAX 10000 |
宏定义是简单的符号代换,这里MAX符号的含义是栈中最多存放10000个结点的地址 |
typedef struct{ |
自定义一个结构体类型SeqStack用于 栈操作 |
BiTree data[MAX]; |
定义一个数组类型的变量data,用于存储栈中的元素。 |
int top; |
定义栈的栈顶指针top,它始终指向栈顶元素 |
}SeqStack; |
|
|
|
void in_order_nonrecursive(BiTree T) |
T:根结点的地址 |
{ |
|
SeqStack s; |
声明一个用于栈操作的结构体变量s |
s.top = -1; |
初始化栈顶指针为-1, |
|
|
BiTree p = T; |
变量p是结点地址类型,用于遍历一棵二叉树的各个结点,初始化为树根结点(的地址) |
|
|
while(p || (s.top != -1)){ |
外层while循环:用于找到每一个左枝的第一个结点,这个结点是上一个左枝的最后一个结点的右孩子 |
while(p){ |
内层while循环: 把P结点的左枝上的所有结点入栈, 仅仅是结点的入栈操作,没有访问操作。 因为左枝上的每一个结点都是其子树的根结点, 中序遍历是:左根右,要先递归访问(打印)到左枝上的最后一个左结点,所以作为枝上的这些结点都需要入栈,以备后续进行访问(打印) |
if(s.top == MAX - 1){ |
如果栈满 |
exit(0); |
不进行任何操作,直接退出 |
} |
|
|
如果栈不满 |
s.data[++s.top]=p; |
把当前这个p结点地址入栈(入栈前要先把栈顶栈顶指针加1,因为栈顶指针的初始值是-1,而数组是从下标为0的单元开始存放数据),因为中序遍历是:左根右,在没有找到左枝的最后一个结点之前,这些结点都要入栈,用于后序的重新访问(打印结点操作) |
p=p->lchild; |
更新当前结点为这个结点的左孩子 |
} |
内层while循环结束,表示当前p是空结点,而栈顶元素是左枝上的最后一个结点 |
|
|
if(s.top!=-1){ |
如果栈不空 |
p = s.data[s.top--]; |
从栈中通过栈顶指针取出栈顶元素(左枝上的最后一个结点),并作为栈操作的配套操作,把栈顶指针减1 |
printf("%c",p->data); |
这个刚从栈顶取出的元素是之前左枝上的最后一个元素,这个元素自然就没有左孩子,所以直接访问(这里是打印操作)这个结点 |
p=p->rchild; |
访问(打印)完这个结点,就立即把结点更新为它的右孩子。因为中序遍历:左根右,没有左孩子,又把这个没有左孩子的结点访问完毕,接下来就要对以其右孩子为首的左枝进行while操作(下一次内层while操作) |
} |
|
} |
|
|
|
printf("\n"); |
|
} |
|
|
代码:
#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 in_order_nonrecursive(BiTree T)
{
SeqStack s;
s.top = -1;
BiTree p = T;
while(p || (s.top != -1)){
while(p){
if(s.top == MAX - 1){
exit(0);
}
s.data[++s.top]=p;
p=p->lchild;
}
if(s.top!=-1){
p = s.data[s.top--];
printf("%c",p->data);
p=p->rchild;
}
}
printf("\n");
}