您的位置:首页 > 其它

利用栈实现二叉树的后序遍历算法

2015-08-06 12:37 218 查看
二叉树的后序遍历算法是按照左子树->右子树->节点的访问顺序来遍历二叉树的。所以需要将节点依次入栈,然后分别找到他们的左子树和右子树。而且在右子树没有被访问完之前,节点要一直在栈中。所以,当我们访问左子树后根据节点去访问右子树,而当右子树访问完后访问节点退栈,两次访问节点结果却不相同,如下图:



一个是访问节点后去访问右子树,一个是访问节点后退栈访问上一个节点的右子树如果不做任何处理,那么会在右子树访问后形成死循环,所以应添加一个标致位标致访问节点时应访问的位置(先序遍历和中序遍历并不需要,因为他们在访问右子树之前就已经将节点出栈了)。

首先定义栈元素类型:

typedef struct {

struct BiTNode *ptr; // 二叉树结点的指针类型

int tag; // 0..1

} SElemType; // 栈的元素类型

二叉树节点类型:

typedef struct BiTNode {

TElemType data;

struct BiTNode *lchild,*rchild;

} BiTNode, *BiTree;

栈的操作函数,自己实现,此处不再赘叙。主要有:

Status InitStack(Stack &S); //初始化栈

Status StackEmpty(Stack S); //判断栈是否为空,这是后序遍历是否完成的标致

Status Push(Stack &S, SElemType e);//入栈

Status Pop(Stack &S, SElemType &e); //出栈

Status GetTop(Stack S, SElemType &e); //得到栈顶元素,栈顶元素并不出栈

算法实现主要思想:

先到最左下角的元素,然后判断它是否有右子树,若是则将它的标致域标为1,并重复上面步骤,把指针移向它的右子树最左下角的元素,直到最左下角元素没有了右子树后访问他,并判断它的上一个节点有没有右子树,若有,将它的上一个节点的标致域置为1并将指针指向它的右子树,重复上面步骤。若没有则访问这个节点直到它上一个有了右子树为止或栈空,遍历完成,退出循环。



后序遍历代码:

void PostOrder(BiTree T, void (*visit)(TElemType))

/* 使用栈,非递归后序遍历二叉树T, */

/* 对每个结点的元素域data调用函数visit */

{

if(T == null)

return ;

SElemType *st,a;

st = (SElemType*) malloc (sizeof(SElemType));

st->ptr = T;

st->tag = 0;

Stack s;

InitStack(s);

while(1)

{

while(st->ptr->lchild)

{

st->tag = 0;

Push(s,*st);

st->ptr = st->ptr->lchild;

}

if(st->ptr->rchild)

{

st->tag = 1;

Push(s,*st);

st->ptr = st->ptr->rchild;

continue;

}

else

{

visit(st->ptr->data);

GetTop(s, a);//此处因每次出栈用指针都报语法错误,不知为何,不得已而为之

*st = a;

while(!st->ptr->rchild||st->tag == 1)

{

Pop(s,a);

visit(st->ptr->data);

GetTop(s, a);

*st = a;

if(StackEmpty(s))

{

free(st);

return;

}

}

Pop(s,a);

a.tag = 1;

Push(s,a);

st->ptr = st->ptr->rchild;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: