二叉树的三种非递归遍历方法

1. 前序遍历

前序遍历根在最前面。实现起来比较简单,使用一个栈就OK了。

对于每一个节点,我们直接访问它,并把它的右儿子压入栈中,之后我们移动指针来访问左儿子。

到头了之后就把右儿子从站里pop出来。

ClearStack(S);
p = bt;
while (1){
	if (p == NULL){
		if (EmptyStack(S)) break;
		p = Pop(S);
	}
	visit(p);
	if (p->Rchild != NULL) Push(S, p->Rchild);
	p = p->Lchild;
}

2.中序遍历

中序遍历的难度和前序类似。首先我们从根节点出发,一路向左走到最左边。期间遇到的节点都压栈。

之后,我们从最左侧开始访问栈中节点,并访问其右子树。

ClearStack(S);
p = bt;
while (1){
	while (p){
		Push(S, p);
		p = p->Lchild;
	}
	if (EmptyStack(S)) break;

	//此时应访问刚进栈的
	p = Pop(S);
	visit(p);
	p = p->Rchild; //访问右子树
}

3.后序遍历

后序遍历相比起来复杂一些,但基本思路和中序类似。

后序遍历的顺序是 左-右-根,同样需要先向左走到头,但是回头的时候不能立刻访问根节点,而是用结构体标记一下,继续入栈,之后继续访问右节点并遍历。如果出栈的根节点是标记过的,那才说明它下面的节点都被访问过了,可以放心pop出去。

//定义栈元素类型:
typedef struct {
    BTptr q; //节点地址
    int tag;  //标志
} STYPE;

STYPE sdata;
ClearStack(S);
p = bt;
while (1)
{
	while (p)
	{
		sdata.q = p;
		sdata.tag = 0;
		Push(S, sdata);
		p = p->Lchild;
	}
	if (EmptyStack(S)) break;
	sdata = Pop(S);
	p = sdata.q;
	tag = sdata.tag;

	if (tag == 0)   //应先遍历右子树
	{
		sdata.tag = 1;
		Push(S, sdata);
		p = p->Rchild; // 访问右子树
	}
	else
	{
		visit(p);
		p = NULL;
	}
}

 

猜你喜欢

转载自blog.csdn.net/timotolkki1966/article/details/80428026