1. 程式人生 > >第4章第1節練習題2 二叉樹的基本操作(非遞迴實現)

第4章第1節練習題2 二叉樹的基本操作(非遞迴實現)

二叉樹的非遞迴遍歷

上一節二叉樹的遞迴遍歷中簡單介紹了二叉樹的遞迴遍歷的實現方式,本節主要介紹二叉樹的非遞迴遍歷實現,繼續引用上節的例子來說明下。

Order

一.先序遍歷

二叉樹先序遍歷的訪問順序為:根結點->左孩子->右孩子。簡單的說,對於任意一個結點,均可以看作是根結點,直接對其訪問,如果訪問完成後,左孩子不為空,則可以將該左孩子再次看成一個新的根結點,那麼就又回到開始,訪問根結點,訪問左孩子,如果左孩子為空時,訪問它的右孩子。對於一般程式而言,遞迴程式轉為非遞迴程式需要引入這個資料結構,可以參考第2章第1節 棧的基本定義以及實現方式,其處理過程可以簡單分為三步:

對於任一結點T:

  1. 訪問結點T,並將結點T入棧;
  2. 判斷結點T的左孩子是否為空,若不為空,則將結點T的左孩子入棧;再判斷T的右孩子是否為空,若不為空,則將結點T的右孩子入棧;若為左孩子或右孩子為空,則出棧訪問。這裡應該注意到棧的先進後出的特性,因此需要先將右孩子入棧,再將左孩子入棧;
  3. 最後直到棧為空便結束訪問。

演算法描述如下:

void PreOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode* p=T;
    Push(&S,p);
    while(IsEmptyStack(&S)!=0){
        p=Pop(&S);
        printf
("%c",p->data); if(p->rchild!=NULL){ Push(&S,p->rchild); } if(p->lchild!=NULL){ Push(&S,p->lchild); } } }

二.中序遍歷

二叉樹中序遍歷的訪問順序為左孩子->根結點->右孩子。簡單來說就是:先掃描(不訪問)根結點的所有左孩子並將它們一一入棧,然後出棧一個結點*p並且訪問它,然後掃描該結點*p的右孩子,並將其入棧,再掃描以該結點*p

的右孩子為根結點的所有左孩子,並將其一一入棧,如此繼續,直到棧為空為止。其處理過程可以簡單分為三步:

對於任一結點T:

  1. 首先判斷結點T是否為空,若不為空,則將其入棧,然後讓指標p指向結點T的左孩子;接著繼續重複該步驟,直到結點T為空為止;
  2. 經過第一步可以保證棧頂元素一定是該二叉樹最左的孩子結點,然後出棧訪問該結點,接著判斷其右孩子是否為空,若不為空,接著掃描右孩子的左孩子結點,重複第1步;
  3. 最後直到棧為空時便結束訪問。

演算法描述如下:

void InOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode* p=T;

    while(p||IsEmptyStack(&S)!=0){
        if(p!=NULL){
            Push(&S,p);
            p=p->lchild;
        }else{
            p=Pop(&S);
            printf("%c",p->data);
            p=p->rchild;
        }
    }
}

三. 後序遍歷

二叉樹中序遍歷的訪問順序為左孩子->右孩子->根結點。因為後序非遞迴遍歷二叉樹的順序是先訪問左孩子,再訪問右孩子,最後訪問根結點。所以當用棧來儲存結點時,必須分清返回根結點時是從左孩子返回的還是從右孩子返回的,需要設定一個輔助指標r,讓其指向最近訪問過的結點。其處理過程可以簡單分為三步:

對於任一結點T:

  1. 首先判斷根結點是否為空,若不為空,則不斷的入棧直到最左邊的左孩子結點為止;
  2. 接著取出棧頂結點,判斷其右孩子是否為空,而且其右孩子沒有被訪問過,接著對其右孩子入棧,再重複第1,2步;
  3. 但是若右孩子為空,則出棧訪問,並對該結點標記。

演算法描述如下:

void PostOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode *p=T;
    BiTNode *r=NULL;

    while(p||IsEmptyStack(&S)!=0){
        if(p!=NULL){
            Push(&S,p);
            p=p->lchild;
        }else{
            p=GetTop(&S);
            if(p->rchild!=NULL&&p->rchild!=r){
                p=p->rchild;
                Push(&S,p);
                p=p->lchild;
            }else{
                p=Pop(&S);
                printf("%c",p->data);
                r=p;
                p=NULL;
            }
        }
    }
}

四.層次遍歷

一般的二叉樹層次遍歷是自上而下,自左向右。簡單來說就是先訪問根結點,然後訪問其左孩子,右孩子,可以藉助佇列的特性先進先出來實現層次遍歷,可以參考第2章第2節 佇列的基本定義以及實現方式,其處理過程可以簡單分為三步:

對於任一結點T:

  1. 訪問結點T,然後將結點T入隊;
  2. 出隊訪問該結點,然後判斷其左孩子和右孩子是否為空,如果不為空,則分別將其入隊;
  3. 若為空,出隊訪問便可;
void PostOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode *p=T;
    BiTNode *r=NULL;

    while(p||IsEmptyStack(&S)!=0){
        if(p!=NULL){
            Push(&S,p);
            p=p->lchild;
        }else{
            p=GetTop(&S);
            if(p->rchild!=NULL&&p->rchild!=r){
                p=p->rchild;
                Push(&S,p);
                p=p->lchild;
            }else{
                p=Pop(&S);
                printf("%c",p->data);
                r=p;
                p=NULL;
            }
        }
    }
}

具體程式碼見附件

附件

//AB#DF###C#E##
#include<stdio.h>
#include<stdlib.h>

#define MaxSize 100
typedef char ElemType;

/*-----------------------------------------*/

typedef struct BiTNode{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

BiTNode* CreateBiTree(BiTNode*);
void PreOrder(BiTNode*);
void InOrder(BiTNode*);
void PostOrder(BiTNode*);
void LevelOrder(BiTNode*);

/*-----------------------------------------*/

typedef struct SqStack{
    BiTNode* data[MaxSize];
    int top;
}SqStack;

void InitStack(SqStack*);
void Push(SqStack*,BiTNode*);
BiTNode* Pop(SqStack*);
BiTNode* GetTop(SqStack*);
int IsEmptyStack(SqStack*);

typedef struct SqQueue{
    BiTNode* data[MaxSize];
    int front, rear;
}SqQueue;

void InitQueue(SqQueue*);
void EnQueue(SqQueue*, BiTNode*);
BiTNode* DeQueue(SqQueue*);
int IsEmptyQueue(SqQueue*);

/*-----------------------------------------*/

int main(int argc, char* argv[]){
    BiTNode *T=(BiTNode*)malloc(sizeof(BiTNode));
    T=CreateBiTree(T);
    PreOrder(T);printf("\n");
    InOrder(T);printf("\n");
    PostOrder(T);printf("\n");
    LevelOrder(T);printf("\n");
    return 0;
}

//建立二叉樹
BiTree CreateBiTree(BiTNode* T){
    ElemType x;
    scanf("%c",&x);
    if(x=='#'){
        return T;
    }else{
        T=(BiTNode*)malloc(sizeof(BiTNode));
        T->data=x;
        T->lchild=CreateBiTree(T->lchild);
        T->rchild=CreateBiTree(T->rchild);
    }
    return T;
}

//先序遍歷
void PreOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode* p=T;
    Push(&S,p);
    while(IsEmptyStack(&S)!=0){
        p=Pop(&S);
        printf("%c",p->data);
        if(p->rchild!=NULL){
            Push(&S,p->rchild);
        }
        if(p->lchild!=NULL){
            Push(&S,p->lchild);
        }
    }
}

//中序遍歷
void InOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode* p=T;

    while(p||IsEmptyStack(&S)!=0){
        if(p!=NULL){
            Push(&S,p);
            p=p->lchild;
        }else{
            p=Pop(&S);
            printf("%c",p->data);
            p=p->rchild;
        }
    }
}

//後序遍歷
void PostOrder(BiTNode* T){
    SqStack S;
    InitStack(&S);

    BiTNode *p=T;
    BiTNode *r=NULL;

    while(p||IsEmptyStack(&S)!=0){
        if(p!=NULL){
            Push(&S,p);
            p=p->lchild;
        }else{
            p=GetTop(&S);
            if(p->rchild!=NULL&&p->rchild!=r){
                p=p->rchild;
                Push(&S,p);
                p=p->lchild;
            }else{
                p=Pop(&S);
                printf("%c",p->data);
                r=p;
                p=NULL;
            }
        }
    }
}

//層次遍歷
void LevelOrder(BiTNode* T){
    SqQueue Q;
    InitQueue(&Q);

    BiTNode *p=T;
    EnQueue(&Q,p);

    while(IsEmptyQueue(&Q)!=0){
        p=DeQueue(&Q);
        printf("%c",p->data);
        if(p->lchild!=NULL){
            EnQueue(&Q,p->lchild);
        }
        if(p->rchild!=NULL){
            EnQueue(&Q,p->rchild);
        }
    }
}

/*-----------------------------------------*/

void InitStack(SqStack* S){
    S->top=-1;
}

void Push(SqStack* S, BiTNode* T){
    if(S->top==MaxSize-1){
        return;
    }
    S->data[++S->top]=T;
}

BiTNode* Pop(SqStack* S){
    if(S->top==-1){
        return NULL;
    }
    return S->data[S->top--];

}

BiTNode* GetTop(SqStack* S){
    if(S->top==-1){
        return NULL;
    }
    return S->data[S->top];
}

int IsEmptyStack(SqStack* S){
    if(S->top==-1){
        return 0;
    }
    return -1;
}

/*-----------------------------------------*/

void InitQueue(SqQueue* Q){
    Q->front=0;
    Q->rear=0;
}

void EnQueue(SqQueue* Q, BiTNode* T){
    if((Q->rear+1)%MaxSize==Q->front){
        return;
    }
    Q->data[Q->rear++]=T;
}

BiTNode* DeQueue(SqQueue* Q){
    if(Q->front==Q->rear){
        return NULL;
    }
    return Q->data[Q->front++];
}

int IsEmptyQueue(SqQueue* Q){
    if(Q->front==Q->rear){
        return 0;
    }
    return -1;
}