C語言 二叉樹的遍歷 遞迴和(多種)非遞迴演算法
阿新 • • 發佈:2019-01-05
//二叉樹遍歷 //作者:nuaazdh //時間:2011年12月1日 #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define OVERFLOW -1 #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 typedef int Status; typedef char ElemType; // 二叉樹結點元素型別 typedef struct BiTNode{ // 二叉樹結點結構 char data; // 結點資料 struct BiTNode *lchild; // 左孩子 struct BiTNode *rchild; // 右孩子 }BiTNode,*BiTree; typedef BiTree SElemType; typedef struct{//棧結構定義 SElemType *base; SElemType *top; int stacksize; }SqStack; Status InitStack(SqStack *S); //構造一個空棧S Status DestroyStack(SqStack *S); //銷燬棧S,S不再存在 Status ClearStack(SqStack *S); //把棧S置為空棧 Status StackEmpty(SqStack S); //若棧S為空棧,則返回TRUE,否則返回FALSE int StackLength(SqStack S); //返回S元素的個數,即棧的長度 Status GetTop(SqStack S,SElemType *e); //若棧不為空,則用e返回S的棧頂元素,並返回OK;否則返回FALSE Status Push(SqStack *S,SElemType e); //插入元素e為新的棧頂元素 Status Pop(SqStack *S,SElemType *e); //若棧S不為空,則刪除S的棧頂元素,用e返回其值,並返回OK,否則返回ERROR Status StackTraverse(const SqStack *S); //從棧底到棧頂依次對每個元素進行訪問 BiTree CreateBiTree(BiTree T); // 按先後次序輸入二叉樹中結點的值(一個字元),空格表示空樹 // 構造二叉連結串列表示的二叉樹T Status PreOrderRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)); // 採用二叉連結串列儲存結結構,Visit是對資料元素操作的應用函式 // 先序遍歷二叉樹T的遞迴演算法,對每個資料元素呼叫函式Visit Status InOrderRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)); // 採用二叉連結串列儲存結結構,Visit是對資料元素操作的應用函式 // 中序遍歷二叉樹T的遞迴演算法,對每個資料元素呼叫函式Visit Status PostOrderRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)); // 採用二叉連結串列儲存結結構,Visit是對資料元素操作的應用函式 // 後序遍歷二叉樹T的遞迴演算法,對每個資料元素呼叫函式Visit Status PreOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)); // 採用二叉連結串列儲存結結構,Visit是對資料元素操作的應用函式 // 先序遍歷二叉樹T的非遞迴演算法,對每個資料元素呼叫函式Visit Status InOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)); // 採用二叉連結串列儲存結結構,Visit是對資料元素操作的應用函式 // 中序遍歷二叉樹T的非遞迴演算法,對每個資料元素呼叫函式Visit Status PostOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)); // 採用二叉連結串列儲存結結構,Visit是對資料元素操作的應用函式 // 後序遍歷二叉樹T的非遞迴演算法,對每個資料元素呼叫函式Visit Status Visit(ElemType e); // 對二叉樹中的資料元素訪問 int main() { BiTree T=NULL; Status(*visit)(ElemType e)=Visit; printf("請按先序遍歷輸入二叉樹元素(每個結點一個字元,空結點為'#'):\n"); T=CreateBiTree(T); printf("\n遞迴先序遍歷:\n"); PreOrderRecursionTraverse(T,visit); printf("\n遞迴中序遍歷:\n"); InOrderRecursionTraverse(T,visit); printf("\n遞迴後序遍歷:\n"); PostOrderRecursionTraverse(T,visit); printf("\n非遞迴先序遍歷:\n"); PreOrderNonRecursionTraverse(T,visit); printf("\n非遞迴中序遍歷:\n"); InOrderNonRecursionTraverse(T,visit); printf("\n非遞迴後序遍歷:\n"); PostOrderNonRecursionTraverse(T,visit); printf("\nEnd of main.\n"); return 0; } BiTree CreateBiTree(BiTree T){ // 按先後次序輸入二叉樹中結點的值(一個字元),空格表示空樹 // 構造二叉連結串列表示的二叉樹T char ch; scanf("%c",&ch); if(ch=='#') T=NULL; else{ if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) exit(OVERFLOW); T->data=ch; // 生成根節點 T->lchild=CreateBiTree(T->lchild); // 構造左子樹 T->rchild=CreateBiTree(T->rchild); // 構造右子樹 } return T; } Status PreOrderRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)) { // 先序遍歷遞迴演算法 if(T){ if(!Visit(T->data)) return ERROR; PreOrderRecursionTraverse(T->lchild,Visit); PreOrderRecursionTraverse(T->rchild,Visit); } return OK; } Status InOrderRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)) { // 中序遍歷遞迴演算法 if(T){ InOrderRecursionTraverse(T->lchild,Visit); if(!Visit(T->data)) return ERROR;; InOrderRecursionTraverse(T->rchild,Visit); } return OK; } Status PostOrderRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)) { //後序遍歷遞迴演算法 if(T){ PostOrderRecursionTraverse(T->lchild,Visit); PostOrderRecursionTraverse(T->rchild,Visit); if(!Visit(T->data)) return ERROR;; } return OK; } Status PreOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)){ // 先序遍歷二叉樹T的非遞迴演算法 SqStack S; SElemType p; InitStack(&S); Push(&S,T); // 根指標入棧 while(!StackEmpty(S)){ Pop(&S,&p); //訪問根節點 if(!Visit(p->data)) return ERROR; if (p->rchild) Push(&S,p->rchild); if(p->lchild) Push(&S,p->lchild); }//while DestroyStack(&S); return OK; } /**演算法一 Status InOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)){ // 中序遍歷二叉樹T的非遞迴演算法 SqStack S; SElemType p; InitStack(&S); Push(&S,T); // 根指標入棧 while(!StackEmpty(S)){ while(GetTop(S,&p)&&p) Push(&S,p->lchild); //向左走到盡頭 Pop(&S,&p); //空指標出棧 if(!StackEmpty(S)){//訪問結點,向右一步 Pop(&S,&p); if(!Visit(p->data)) return ERROR; Push(&S,p->rchild); }//if }//while DestroyStack(&S); return OK; } */ Status InOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)){ // 中序遍歷二叉樹T的非遞迴演算法 SqStack S; SElemType p; 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; }//else }//while DestroyStack(&S); return OK; } /**演算法一 Status PostOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)){ // 後序遍歷二叉樹T的非遞迴演算法 SqStack S; SElemType p,q; InitStack(&S); Push(&S,T); // 根指標入棧 while(!StackEmpty(S)){ while(GetTop(S,&p)&&p&&(p->lchild||p->rchild)){ Push(&S,p->rchild); // 右子樹入棧 Push(&S,p->lchild); // 左子樹入棧 }//注意棧中存在空指標,表示某個結點的右子樹為空 if(!StackEmpty(S)){//訪問結點 Pop(&S,&p); if (p){ if(!Visit(p->data)) return ERROR; }else{ // 存在右子樹為空的結點,繼續向上返回 Pop(&S,&p); if(!Visit(p->data)) return ERROR; } while (GetTop(S,&q)&&q&&p==q->rchild){//若當前為右子樹,則繼續出棧 Pop(&S,&p); if(!Visit(p->data)) return ERROR; GetTop(S,&q); } }//if }//while DestroyStack(&S); return OK; } */ /***演算法二*/ Status PostOrderNonRecursionTraverse(BiTree T,Status (*Visit)(ElemType e)){ // 後序遍歷二叉樹T的非遞迴演算法 SqStack S; SElemType p,q; InitStack(&S); Push(&S,T); // 根指標入棧 while(!StackEmpty(S)){ while(GetTop(S,&p)&&p) Push(&S,p->lchild); //向左走到盡頭 Pop(&S,&p); //空指標出棧 GetTop(S,&p); if(p->rchild){ Push(&S,p->rchild); continue; } if(!StackEmpty(S)){//訪問結點,向右一步 Pop(&S,&p); if(!Visit(p->data)) return ERROR; while (GetTop(S,&q)&&q&&p==q->rchild){//若當前為右子樹,則繼續出棧 Pop(&S,&p); if(!Visit(p->data)) return ERROR; } GetTop(S,&p); if(p->rchild){ Push(&S,p->rchild); continue; }else{ Pop(&S,&p); if(!Visit(p->data)) return ERROR; } }//if }//while DestroyStack(&S); return OK; } Status Visit(ElemType e){ // 對二叉樹中的資料元素訪問 if(e=='\0'){ return ERROR; }else{ printf("%c",e); } return OK; } //-----------順序棧操作--------------// Status InitStack(SqStack *S){ //構造一個空棧S S->base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!S->base)//分配失敗 { printf("分配記憶體失敗.\n"); exit(0); } S->top=S->base; S->stacksize=STACK_INIT_SIZE; return OK; } Status DestroyStack(SqStack *S){ //銷燬棧S,S不再存在 if(!S)//S為空 { printf("指標為空,釋放失敗.\n"); exit(0); } free(S->base); return OK; } Status ClearStack(SqStack *S){ //把棧S置為空棧 if(!S)//S不存在 return FALSE; S->top=S->base;//直接將棧頂指標指向棧底 return OK; } Status StackEmpty(SqStack S){ //若棧S為空棧,則返回TRUE,否則返回FALSE if(S.top==S.base) return TRUE; else return FALSE; } int StackLength(SqStack S){ //返回S元素的個數,即棧的長度 return S.stacksize; } Status GetTop(SqStack S,SElemType *e){ //若棧不為空,則用e返回S的棧頂元素,並返回OK;否則返回FALSE if(S.top==S.base){ return FALSE; }else{ *e=*(S.top-1); return OK; } } Status Push(SqStack *S,SElemType e){ //插入元素e為新的棧頂元素 if(S->top-S->base>=S->stacksize){//棧已滿,追加儲存空間 S->base=(SElemType *)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(SElemType)); if(!S->base) { printf("重新申請空間失敗.\n"); exit(0); } S->top=S->base+S->stacksize;//更改棧頂指標 S->stacksize+=STACKINCREMENT; } *S->top++=e; return OK; } Status Pop(SqStack *S,SElemType *e){ //若棧S不為空,則刪除S的棧頂元素,用e返回其值,並返回OK,否則返回ERROR if(S->top==S->base){//棧為空 return ERROR; } *e=*(--S->top); return OK; }
執行結果: