前言
- 二叉树的前序、中序、后序遍历的非递归实现均采用栈作为中间存储
前序遍历
- 思路:现将根节点存储到栈中,然后开始循环:从栈中拿出一个节点,相应的就要将这个节点的非空右子女和非空左子女依次放入栈中。直至栈为空。
- 代码:
void PreOrder(BTNode *root,int n){
BTNode **S;
int top;
top = -1;
BTNode *p;
S = (BTNode **)malloc((n+1)* sizeof(BTNode *));
S[++top] = root;
while (top != -1){
p = S[top--];
printf("%d\t",p->data);
if (p->right){
S[++top] = p->right;
}
if (p->left){
S[++top] = p->left;
}
}
free(S);
}
中序遍历
- 思路:从根节点开始,若当前节点存在,则当前节点进入栈,并进入其左子树;否则,退栈并访问出栈节点,然后进入其右子树。循环判断条件:当前根节点存在或者栈不为空。
- 代码:
void InOrder(BTNode *root,int n)
{
BTNode **S;
int top;
top = -1;
BTNode *p;
S = (BTNode **)malloc((n+1)* sizeof(BTNode *));
p = root;
while (p || top != -1)
{
if(p){
S[++top] = p;
p = p->left;
}else{
p = S[top--];
printf("%d\t",p->data);
p = p->right;
}
}
free(S);
}
后序遍历
- 思路
从根节点开始,若当前节点存在,则进栈,并进入其左子树;否则,判断栈顶节点的右子树是否为空、右子树是否进入过;是,则退栈,访问该节点,p赋给q,p为空;不是,则进入右子树。(书上的概念)
我的理解是:后序遍历过程中,根节点的输出是在其右子女输出之后的。那么,就存在两种情况:1.右子女为空,则直接输出根节点;2.右子女不为空,则必须能够表示出该右子女是否被访问过,所以会有中间变量q
- 代码
void PostOrder(BTNode *root,int n)
{
BTNode **S;
int top;
top = -1;
BTNode *p,*q;
q = NULL;
S = (BTNode **)malloc((n+1)* sizeof(BTNode *));
p = root;
while (top != -1 || p)
{
if(p){
S[++top] = p;
p = p->left;
}else{
p = S[top];
if(p->right && p->right !=q)
{
p = p-> right;
}else{
p = S[top--];
printf("%d\t",p->data);
q = p;
p = NULL;
}
}
}
free(S);
}