二叉树是一种特殊的树,每个节点都有左右两个子树。
其递归算法为(以先序为例):
1.访问根节点;
2.先序访问左子树;
3.先序访问右子树。
Bool PreOdTree(Bitree T,bool (*visit) (int e))
{
bool Print(int e)
{
printf(e);
return OK;
}
if(T)
{
if(visit(T->data))
if(PreOdTree(T->lchild,visit));
if(PreOdTree(T->rchild,visit));
return OK;
}
else return OK;
}
其非递归算法描述如下(以中序为例):
由于要先访问节点的左子树,因此要寻找根的左子树,再找该节点的左子树,一直找下去,直到该点没有左子树为止。
由于他一直向下寻找到尽头还要回来,为了防止其迷路,因此要进行一些标记,由于先寻找到的后访问,所以要采取栈的数据结构。
我们将含有左子树的节点均压栈,然后访问没有左子树的节点,到尽头后,弹出当前栈中的节点表示退回上一层,再寻找一步该点的右子树,再从其右子树出发寻找左子树直到尽头,方法同前。
算法如下:
首先将一直向左寻找这一步骤封装为一个函数。
BiNode* GetLeft(BiTree T,stack *S)
{
while(T->lchild)
{
push(S,T);
T=T->lchild;
}
return T;
}
然后执行上述方法:
Bool MidFind(BiTree T, bool (visit*) (int e))
{
Stack *S;
t=GetLeft(T,S);
while(t)
{
visit(t->data);
//pop(S);
if(t->rchild)
{
t=GetLeft(t->rchild,S);
}
else if(!Stack(S))
POP(S);
else return NULL;
}
这就完成了二叉树的中序遍历。
先序遍历与中序遍历极为类似,先序遍历也是一个找左子树的过程,但是在每次找左子树之前都要先访问此节点的数据。
因此将上述的Getleft改为:
BiNode* GetLeft11(BiTree T,stack *S)
{
while(T->lchild)
{
visit(T->data);
push(S,T);
T=T->lchild;
}
return T;
}
主程序中将visit(t->data)删除即可。
解释为先访问根节点,然后寻找其左子树,找到尽头后,向上弹回一层,寻找右子树。不过在做所有事之前各个根节点已经保存下来并最先访问了。