结合栈实现非递归遍历
先序遍历思想如下:
步骤1:若当前结点有右子树,则将右子树结点压入栈,输出当前节点并指针往下走指向该节点的左子树。
步骤2:若左子树为空,则遍历右子树,重复步骤1,若右子树为空,弹栈输出指针指向该结点。
中序遍历思想如下:
步骤1:若当前结点有左子树,则将当前结点压入栈,指针往下走指向该节点的左子树
(相当于一直到最左下方),若无左子树了,则输出该结点。
步骤2:若当前结点有右子树,则指针指向该右子树,重复步骤1。
若当前结点无右子树,则弹栈,输出栈顶元素,并让指针回退到栈顶元素对应的结点。
若栈为空,则表示遍历结束。
后序遍历思想如下:
步骤1:左子树不为空,将该结点压入栈,遍历左子树
步骤2:左子树为空则输出,在弹栈判断上一级节点右子树为空,则输出该结点,继续弹栈判断
若不为空,则将该结点获取该节点的右子树,并把该结点再次压入栈,遍历右子树。
- 单看理论比较难理解,读者可自行验证一下思想,更好理解。
- 注意:本文未讲述栈模型,读者需有栈的基础知识
先序非递归代码
void unpre_order(BiTNode t)
{
LinkStack *top;
top = LinkStack_Create();;
while(t != NULL || !isempty_linkstack(top)){
if(t!=NULL){
printf("%c",t->data);
if(t->rchild != NULL);
LinkStack_Push(t->rchild, &top);
t = t->lchild;
}else
t = LinkStack_pop(&top);
}
}
中序非递归代码
#include <stdio.h>
#include <string.h>
#include "linkstack.h"
//二叉链
struct BiTNode
{
int data;
struct BiTNode *lchild,*rchild;
};
typedef struct BiTNode BiTNode;
typedef struct BiTNode *BiTree;
BiTNode *goLeft(BiTNode *T, LinkStack *s)
{
if(T == NULL){
return NULL;
}
while(T->lchild != NULL){
LinkStack_Push(s,T);
T = T->lchild;
}
return T;
}
// 非递归中序
void Inorder2(BiTNode *T)
{
BiTNode *t = NULL;
LinkStack *s;
s = LinkStack_Create();
t = goLeft(T,s);
while(t){
printf("%d",t->data);
//若t有右子树,重复步骤1
if(t->rchild != NULL){
t = goLeft(t->rchild,s);
}
//若t没有右子树,根据栈顶指示回退
else if(t->rchild == NULL){
t = LinkStack_Top(s);
LinkStack_pop(s);
}
//若t没有右子树,并且栈为空
else{
t = NULL;
}
}
}
void inOrder(BiTNode *root)
{
if(root == NULL){
return ;
}
//遍历左子树
inOrder(root->lchild);
//打印根结点
printf("%d\n",root->data);
//遍历右子树
inOrder(root->rchild);
}
int main(void)
{
BiTNode t1,t2,t3,t4,t5;
memset(&t1,0,sizeof(BiTNode));
memset(&t2,0,sizeof(BiTNode));
memset(&t3,0,sizeof(BiTNode));
memset(&t4,0,sizeof(BiTNode));
memset(&t5,0,sizeof(BiTNode));
t1.data = 1;
t2.data = 2;
t3.data = 3;
t4.data = 4;
t4.data = 5;
//建立关系
t1.lchild = &t2;
t1.rchild = &t3;
t2.lchild = &t4;
t3.lchild = &t5;
//递归遍历
printf("inOrder\n");
inOrder(&t1);
//非递归遍历
printf("非递归\n");
inOrder2(&t1);
return 0;
}