树的递归遍历比较简单,就是两三句话,相对来说理解二叉树的非递归遍历稍微难一点。
在数据结构上,有二叉树的中序遍历非递归算法。可以根据中序遍历来写出先序和后序遍历。
在中序遍历时,当非空元素进行出栈时进行访问。访问结束时,右子树结点进栈。会对先序遍历的特点,我们可以得到:
可以在元素进栈的过程中,访问元素,这样就可以先序访问了。和中序遍历比,进行顺序都一样。
对于后序遍历,可能和两者不太一样。根结点要最后输出。所以根结点要在左子树和右子树返回后,才访问。
所以根结点要记录一下,是从左子树返回,还是右子树返回。当从右子树返回时,输出。
以下为实现代码,供参考
中序遍历:
void inorder_traverse(BiTree t)
{
stack s;
create_stack(&s, sizeof(BiTree), 50);//创建一个可容纳50个元素的栈
PUSH(s, t);
BiTree p = NULL;
while (!is_empty(&s)){
while (GETTOP(s, p) && p!=NULL) PUSH(s, p->lchild);
POP(s, p);
if (!is_empty(&s)){ //访问节点
POP(s, p);
printf("%c\t", p->data);
PUSH(s, p->rchild);
}
}
free_stack(&s);
}
先序遍历
void pre_order_traverse(BiTree t)
{
stack s;
create_stack(&s, sizeof(BiTree), 50);
PUSH(s, t);
BiTree p = NULL;
while (!is_empty(&s)){
while (GETTOP(s, p) && p!=NULL) {
printf("%c\t", p->data);
PUSH(s, p->lchild);
}
POP(s, p);
if (!is_empty(&s)){ //访问节点
POP(s, p);
PUSH(s, p->rchild);
}
}
free_stack(&s);
}
后序遍历
struct stack_node
{
BiTree ptree;
unsigned char times;
};
void after_order_traverse(BiTree t)
{
stack s;
create_stack(&s, sizeof(struct stack_node), 50);
struct stack_node p, item;
p.ptree = t;
p.times = 0;
PUSH(s, p);
while (!is_empty(&s)){
while (GETTOP(s, p) && p.ptree!=NULL){
item.ptree = p.ptree->lchild;
item.times = 0;
PUSH(s, item);
}
POP(s, p);
while (!is_empty(&s)){ //成为栈顶元素,计数。两次栈顶即可输出
//栈顶元素计数加1
struct stack_node *pnode = NULL;
pnode = (struct stack_node *)get_top_point(&s);//得到栈顶元素指针,方便对栈顶元素修改
pnode->times++;
if (pnode->times==1){
p.ptree = pnode->ptree->rchild;
p.times = 0;
PUSH(s, p); //右孩子入栈
break;
} else { //p.times == 2 输出
POP(s, p);
printf("%c\t", p.ptree->data);
}
}
}
free_stack(&s);
}