【边学边记】之二叉树的遍历
定义:二叉树遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。
遍历方式:从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
⑴访问结点本身(N),
⑵遍历该结点的左子树(L),
⑶遍历该结点的右子树(R)。
以上三种操作有六种执行次序:
NLR、LNR、LRN、NRL、RNL、RLN。
注意: 前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。
NLR:前序遍历(PreorderTraversal亦称(先序遍历))
若二叉树非空,则依次执行如下操作:
⑴ 访问根结点;
⑵ 遍历左子树;
⑶ 遍历右子树。
LNR:中序遍历(InorderTraversal)
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵访问根结点;
⑶遍历右子树。
LRN:后序遍历(PostorderTraversal)
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。
层序遍历
除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
前序遍历:abdefgc
中序遍历:debgfac
后序遍历:edgfbca
层序遍历:abcdfeg
代码实现
前序遍历:
//递归先序遍历
void PreOrder(Tree t)
{
if ( t )
{
printf("%c",t->data);
PreOrder(t->lchild);
PreOrder(t->rchild);
}
}
//非递归先序遍历
void PreOrder1(Tree t)
{
Tree p = t;
Sqstack s;
InitStack(s);
while ( p || !StackEmpty(s) )
{
if ( p )
{
printf("%c",p->data);
Push(s,p);
p = p->lchild;
}
else
{
Pop(s,p);
p = p->rchild;
}
}
}
中序遍历
//递归中序遍历
void InOrder(Tree t)
{
if ( t )
{
InOrder(t->lchild);
printf("%c",t->data);
InOrder(t->rchild);
}
}
//非递归中序遍历
void InOrder1(Tree t)
{
Tree p = t;
Sqstack s;
InitStack(s);
while ( p || !StackEmpty(s) )
{
if ( p )
{
Push(s,p);
p = p->lchild;
}
else
{
Pop(s,p);
printf("%c",p->data);
p = p->rchild;
}
}
}
后序遍历
//递归后序遍历
void PostOrder(Tree t)
{
if ( t )
{
PostOrder(t->lchild);
PostOrder(t->rchild);
printf("%c",t->data);
}
}
//非递归后序遍历
void PostOrder1(Tree t)
{
t->isOut = 0;
Tree p = t;
Sqstack s;
InitStack(s);
while ( p || !StackEmpty(s) )
{
if ( p )
{
if ( p->isOut )
{//左右子树都已输出,则该节点也输出
Pop(s,p);
printf("%c",p->data);
if (!StackEmpty(s))
GetTop(s,p); //得到弹出节点元素的父节点
else
p = NULL;
}
else
{
if ( (p->lchild) && (p->lchild->isOut == 1) )
{//如果存在左子树,并且左子树已经遍历完,则说明该节点已经入栈,不用再次Push,直接走向右子树
p->isOut = 1;
p = p->rchild;
}
else
{
Push(s,p);
p = p->lchild;
}
}
}
else
{
if (!StackEmpty(s))
GetTop(s,p);
else
p = NULL;
if ( p->rchild )
{
p = p->rchild;
}
else
{
Pop(s,p);
printf("%c",p->data);
p->isOut = 1;
if (!StackEmpty(s))
{
GetTop(s,p);
if ( p->lchild == NULL )
p->isOut = 1; //右子树已输出,将父节点isOut置1
}
else
p = NULL;
}
}
}
}
分层遍历
void LevelTraverse(BinaryTreeNode * pRoot)
{
if(pRoot == NULL)
return NULL;
queue<BinaryTreeNode *> q;
q.push(pRoot);
while(!q.empty())
{
BinaryTreeNode * pNode = q.front();
q.pop();
Visit(pNode); // 访问节点
if(pNode->m_pLeft != NULL)
q.push(pNode->m_pLeft);
if(pNode->m_pRight != NULL)
q.push(pNode->m_pRight);
}
return;
}
本文代码参考:http://blog.csdn.net/cqnuztq/article/details/8896953
代码部分原文更详细.