1.先序遍历
遍历过程:
1.访问根结点。
2.先序遍历其左子树。
3.先序遍历其右子树。
代码实现(递归):
void PreOrderTraversal(BinTree BT)
{
if(BT){
printf("%d", BT->Data); //访问根结点
PreOrderTraversal( BT->Left); //先序遍历左子树
PreOrderTraversal( BT->Right); //先序遍历右子树
}
}
代码实现(非递归-堆栈):
void PreOrderTraversal(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack( MaxSize); //创建并初始化堆栈S
while( T || !IsEmpty(S))
{
while(T)
{
printf("%5d", T->Data); //(访问)打印结点
T = T->Left;
Push(S,T);
}
if(!IsEmpty(S))
{
T = Pop(S); //结点弹出堆栈
T = T->Right; //转向右子树
}
}
}
图解:
输出结果为:ABDFECGHI
2.中序遍历
遍历过程:
1.中序遍历其左子树
2.访问根结点
3.中序遍历右子树
代码实现(递归):
void InOrderTraversal(BinTree BT)
{
if(BT){
InOrderTraversal( BT->Left); //中序遍历左子树
printf("%d", BT->Data); //访问根结点
InOrderTraversal( BT->Right); //中序遍历右子树
}
}
代码实现(非递归-堆栈):
void InOrderTraversal(BinTree BT)
{
BinTree T = BT;
Stack S = CreatStack( MaxSize); //创建并初始化堆栈S
while( T || !IsEmpty(S))
{
while(T) //一直向左并将沿途结点压入堆栈
{
Push(S,T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Pop(S); //结点弹出堆栈
printf("%5d", T->Data); //(访问)打印结点
T = T->Right; //转向右子树
}
}
}
图解:
输出结果为:DBEFAGHCI
3.后序遍历
遍历过程:
1.后序遍历其左子树
2.后序遍历其右子树
3.访问根节点
代码实现(递归):
void PostOrderTraversal(BinTree BT)
{
if(BT){
PostOrderTraversal( BT->Left); //后序遍历左子树
PostOrderTraversal( BT->Right); //后序遍历右子树
printf("%d", BT->Data); //访问根节点
}
}
图解
输出结果为:DEFBHGICA
共同点
先序、中序和后序便利过程:便利过程中结点的路线一样,只是访问各结点的时机不同。
图中在从入口到出口的曲线上各用赞中符号分别标记出了先序、中序和后序访问结点的时刻。
4.层次遍历
二叉树遍历的核心问题:二维结构的线性化.
1.从结点访问其左、右儿子结点。
2.访问左儿子后,需要用一个存储结构暂时保存不访问的结点。
队列实现:遍历从根结点开始,首先将根节点入队,然后开始执行循环:结点出队、访问该结点、其左右儿子入队。
基本过程 :先根结点入队,然后:
1.从队列中取出一个元素
2.访问钙元素所指结点
3.若钙元素所指结点的左右孩子结点非空,将其左右孩子的指针顺序入队
代码实现
void LevelOrderTraversal( BinTree BT)
{
Queue Q;
BinTree T;
if(!BT) return; //若是空树则直接返回
Q = CreatQueue( MaxSize); //创建并初始化队列Q
AddQ( Q, BT);
while( !IsEmptyQ(Q))
{
T = DeleteQ( Q);
printf("%d\n", T->Data); //访问取出队列的结点
if( T->Left) AddQ( Q, T->Left);
if( T->right) AddQ( Q, T->right);
}
}
应用
1.输出二叉树中的叶子结点
在二叉树的遍历算法中增加检测结点的“左右儿子树是否都为空”
void PreOrderTraversal(BinTree BT)
{
if(BT){
if(!BT->Left && BT->Right)
printf("%d", BT->Data);
PreOrderTraversal( BT->Left); //先序遍历左子树
PreOrderTraversal( BT->Right); //先序遍历右子树
}
}
2.求二叉树的高度
分析:Height = Max(LeftHeigth,RightHeigth)+1
void PostOrderTraversal(BinTree BT)
{
int HL, HR, MaxH;
if(BT){
HL = PostOrderTraversal( BT->Left); //后序遍历左子树
HR = PostOrderTraversal( BT->Right); //后序遍历右子树
MaxH = (HL > HR )? HL : HR; //取左右儿子最大深度
return MaxH+1
}
}
3.二元运算表达式树及其遍历
表达式树:
先序遍历得到前缀表达式:++a*bc*+*defg
中序遍历得到中缀表达式:a+b*c+d*e+f*g
后序遍历得到后缀表达式:abc*+de*f+g*+
注:中缀表达式会收到运算符优先级的影响
可以用加括号的方法。输出左子树时先加一个左括号,输出右子树时再输出右括号。
4.由两种遍历序列确定二叉树
必须要有中序遍历才行!