三种遍历——先、中、后的关系
经过路径相同,但访问时间不同
先序遍历
递归算法
非递归算法
void PreOrderTraversal(BinTree BT)
{
BinTree T=BT;
/*堆栈起到了到达了最左结点后溯回父结点的作用*/
Ptrs S=CreateStack();
while(IsEmpty(S)!=0||T!=NULL){
while(T!=NULL){
printf("%d",T->Data);
Push(S,T);/*第一次经过*/
T=T->Left;}
if(IsEmpty(S)!=0){
T=Pop(S);/*第二次经过*/
T=T->Right;}
}
}
中序遍历
递归算法
非递归算法
void InOrderTraversal(BinTree BT)
{
BinTree T=BT;
Ptrs stack=CreateStack();
while(T!=NULL||IsEmpty(stack)!=0){
while(T!=NULL){
Push(stack,T);
T=T->Next;}
if(IsEmpty(stack)!=0){
T=Pop(stack);
printf("%d",T->Data);
T=T->Right;}
}
}
后序遍历
/*后序非递归遍历算法与中序非递归算法的区别在于:
后序非递归算法在溯回父结点时需判断是第几次经过(即其右儿子是否已经Pop过),
故在Pop该结点前需判断*/
/*可用pre记录最近一次Pop的结点 or 在树结点struct内设flag标记*/
struct SNode{
int Data;
BinTree Left;
BinTree Right;
};
typedef struct SNode* Ptrs;
void PostOrderTraversal(BinTree BT)
{
BinTree T=BT;
BInTree pre=NULL;/*pre用来标记最近一次弹出的结点*/
Ptrs stack=CreateStack();
while(T!=NULL||IsEmpty(stack)!=0){//注意是||的关系
while(T!=NULL){
Push(stack,T);
T=T->Left;}
if(IsEmpty(stack)!=0){
BinTree top=Top(stack);/*Top()函数用来取栈顶值*/
if(top->Right==NULL||top->Right==pre){/*若当前结点没有右儿子或右儿子已经弹出*/
pre=Pop(stack);
printf("%d",pre->Data);}
else T=top->Right;
}
}
}
层序遍历
/*使用队列*/
void LevelOrderTraversal(BinTree BT)
{
BinTree T=BT;
PtrQ Queue=CreateQueue();
if(T==NULL) return;
if(T!=NULL){
AddQ(Queue,T);
while(IsEmpty(Queue)!=0){
T=Delete(Queue);
printf("%d",T->Data);
if(T->Left!=NULL) AddQ(Queue,T->Left);
if(T->Right!=NULL) AddQ(Queue,T->Right);
}
}
二叉树遍历应用
求二叉树的高度
int Height(BinTree BT)
{
BinTree T=BT;
if(T==NULL) return 0;
else{
int HL=Height(T->Left);
int HR=Height(T->Right);
int Max=(HL<HR)?HR:HL;
return Max+1;
}
输出叶子结点
void FindLeaves(BinTree BT)
{
if(BT==NULL) return;
else{
if(BT->Left==NULL&&BT->Right==NULL)
printf("%d",BT->Data);
FindLeaves(BT->Left);
FindLeaves(BT->Right);
}
}
二元运算表达式树及其遍历
由两种遍历序列确定二叉树
由中序和先序(或后序)遍历序列可还原二叉树
/*以先序和中序遍历序列为例,结果以后序遍历方式输出,输出PostOrder[]*/
void Reset(int Pre[],int In[],int Pre_Left,int Post_Left,int I_Left,int N)
{
if(N==1){
PostOrder[Post_Left]=Pre[Pre_Left];/*只有一个元素,直接放入该位置*/
return;}
if(N==0) return;
int Pre_root=Pre_Left;
PostOrder[Post_Left+N-1]=Pre[Pre_root];/*后序:将根放在序列末尾*/
int I_root;
for(I_root=I_Left;I_root<I_Left+N;I_root++)
if(Pre[Pre_root]==In[I_root]) break;
int cL=I_root-I_Left;
int cR=I_Right-I_Left-cL;
Reset(Pre,In,Pre_root+1,Post_Left,I_Left,cL);
Reset(Pre,In,P_root+cL+1,Post_Left+cL,I_root+1,cR);
}