利用栈实现二叉树的后序遍历算法
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;
}
}
}
一个是访问节点后去访问右子树,一个是访问节点后退栈访问上一个节点的右子树如果不做任何处理,那么会在右子树访问后形成死循环,所以应添加一个标致位标致访问节点时应访问的位置(先序遍历和中序遍历并不需要,因为他们在访问右子树之前就已经将节点出栈了)。
首先定义栈元素类型:
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;
}
}
}
相关文章推荐
- GEM5与SystemC混仿结果
- 【Cocos2d入门教程六】Cocos2d-x事件篇之触摸
- MonkeyRunner
- vector使用中的一个疑惑
- 关于返回指针以及动态申请内存
- Codeforces Round #Pi (Div. 2) B Berland National Library
- 软件项目成本法
- HDU 5349 MZL's simple problem(队列)
- excel 关联数据
- AppDelegate.h
- 【暑期基础2】J HDU 2035 人见人爱A^B
- 替换空格
- ABAP 面向对象(Object Orien…
- SAP ERP系统如何通过LS…
- SAP MM Purchase Order里
- C++中的深浅复制_实践示例
- 【Python】Python与文本处理langid工具包的文本语言检测和歧视
- SAP MM 评估收货…
- SAP MM ME51N&nbs…
- SAP MM ME51N&nbs…