二叉树的遍历
二叉树的应用中通常会用到三种遍历方法,前序、中序和后序,对应的遍历顺序是:根左右、左根右、左右根。如果采用二叉链表的存储结构,使用递归实现最简单,下面是用伪代码递归实现的前序遍历:
Status PreOrderTraverse(BiTree T,Status(*Visit))
{//Visit是对数据元素操作的应用函数
if(T)
{
//先访问根节点,然后递归左子树,最后递归右子树
if(Visit(T->data))
if(PreOrderTraverse(T->lchild,Visit))
if(PreOrderTraverse(T->rchild,Visit))
return OK
return ERROR;
}
else return OK;
}
如果递归的左子树是空节点,由于else语句返回了OK,因此会进入右子树的递归遍历;如果该节点以及左右子树都遍历完了,便返回OK;递归调用返回ERROR的情况是:当前访问的节点是空的。
非递归的方法
仿照递归算法执行的工作栈中的状态可以写出非递归的代码,,以下是中序遍历的伪代码:
Status InorderTraverse(BiTree T,(*visit))
{
InitStack(S);//初始化栈
p=T;
while(p||!StackEmpty(S))
{
if(p)//当前节点非空,进栈,并遍历左子树
{
push(S,p);
p=p->lchild;
}
else//根指针退栈,访问根节点,遍历右子树
{
Pop(S,p);
if(!visit(p->data)) return ERROR;
p=p->rchild;
}
}
}
后序遍历稍微复杂,要判断根节点的右子树是否访问过,以下是java版代码:
//二叉树后序遍历非递归算法
static class Node
{
String data;
Node leftChild;
Node rightChild;
}
public void PostorderTraverse(Node node)
{
Stack s = new Stack();
Node currentNode = node;
Node lastNode;
while(currentNode||!s.isEmpty())
{
if(currentNode)//进栈,遍历左子树
{
s.push(currentNode);
currentNode = currentNode.leftChild;
}
else
{//出栈,根据是否遍历右子树来决定是否访问当前节点
s.pop(currentNode);
//右子树已经访问过或者没有右子树
if(currentNode.rightChild==null
||currentNode.rightChild==lastNode)
{
visit(currentNode);
lastNode=currentNode;
}
//入栈,遍历右子树
else if(currentNode.lastNode==lastNode)
{
s.push(currentNode);
currentNode=currentNode.rightChild;
while(currentNode)
{
s.push(currentNode);
currentNode=currentNode.leftChild;
}
}
}
}
}
public void visit(Node node)
{
System.out.print(node.data);
}