二叉樹先序後序遞迴建立,前中後序層次非遞迴遍歷,以及統計葉子結點個數以及樹的深度
阿新 • • 發佈:2019-01-11
下面的程式碼實現了二叉樹的先序或者後序遞迴建立,然後實現了二叉樹的非遞迴的先序中序後序遍歷,還有層次遍歷,以及統計樹的葉子結點個數和樹的深度。其中非遞迴的先中後序遍歷用到了鏈棧,層次遍歷用到了佇列。
程式設計平臺為Visual Studio 2012,語言為C,但不是純C,比如用到了C++的引用機制以及變數的隨時定義(在純C中,變數必須在函式一開始的地方全部宣告)。
// 二叉樹非遞迴遍歷.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdlib.h> #include <string.h> char string[100]; int len; int flag=1; //二叉樹結點結構定義 typedef struct BiTNode { char data; struct BiTNode *lchild; struct BiTNode *rchild; } BiTNode, *BiTree; //鏈棧結點定義 typedef struct StNode { BiTree t; struct StNode *next; }StNode, *StackPtr; //鏈棧定義 typedef struct LinkStack { StackPtr top; int count; } LinkStack, *StLink; //初始化鏈棧 void InitStack(StLink &S) { S=(LinkStack*) malloc(sizeof(LinkStack)); if(!S) exit(EXIT_FAILURE); S->top=NULL; S->count=0; } //為鏈棧插入新的棧頂元素 void Push(StLink &S,BiTree e) { StackPtr s=(StackPtr) malloc(sizeof(StNode)); s->next=S->top; s->t=e; S->top=s; S->count++; } //出棧 void Pop(StLink &S,BiTree &e) { StackPtr p; if(S->count==0) return; e=S->top->t; p=S->top; S->top=S->top->next; free(p); S->count--; } //得到鏈棧的棧頂元素 int Getpop(StLink &S,BiTree &e) { StackPtr p; if(S->count==0) return 0; e=S->top->t; return 1; } //佇列連結串列結構,佇列結點結構域棧一樣,故不重複定義 typedef struct { StackPtr front, rear; //對頭,隊尾指標 int count; }LinkQueue, *QuLink; //初始化佇列 void InitQueue(QuLink &Q) { Q=(QuLink)malloc(sizeof(LinkQueue)); if(!Q) exit(EXIT_FAILURE); Q->front=NULL; Q->rear=NULL; Q->count=0; } //入隊,該佇列為左頭右尾,所以入隊是在最右邊插入 void EnQueue(QuLink &Q,BiTree e) { StackPtr q=(StackPtr)malloc(sizeof(StNode)); if(!q) exit(EXIT_FAILURE); q->t=e; q->next=NULL; if(Q->count==0) //如果此時是空隊 { Q->rear=Q->front=q; } else { Q->rear->next=q; Q->rear=q; } Q->count++; } //出隊,從最左邊出隊 void DeQueue(QuLink &Q,BiTree &e) { StackPtr q; if(Q->count==0) return; if(Q->count==1) { q=Q->front; e=q->t; free(q); Q->front=Q->rear=NULL; Q->count=0; return; } q=Q->front; e=q->t; Q->front=q->next; free(q); Q->count--; } //先序遞迴定義二叉樹,空樹用#代替 void PreCreateBiTree(BiTree &T) { char ch; scanf_s("%c",&ch,1); if(ch=='#') T=NULL; else { T=(BiTree) malloc(sizeof(BiTNode)); if(!T) exit(EXIT_FAILURE); T->data=ch; PreCreateBiTree(T->lchild); PreCreateBiTree(T->rchild); } } //後序序列遞迴定義二叉樹 void PostCreateBiTree(BiTree &T) { if(flag==1) { scanf_s("%s",string,100); len=strlen(string); flag=0; } if(string[--len]=='#') T=NULL; else { T=(BiTree)malloc(sizeof(BiTNode)); if(!T) exit(EXIT_FAILURE); T->data=string[len]; PostCreateBiTree(T->rchild); PostCreateBiTree(T->lchild); } } //非遞迴先序遍歷二叉樹1 void PreOrderTraverse_nonRecursion(BiTree T) { StLink S; BiTree p; InitStack(S); Push(S,T); //根指標進棧 while(S->count!=0) { while(Getpop(S,p)&&p) { printf("%c",p->data); Push(S,p->lchild);} //向左走到盡頭 Pop(S,p); //空指標退棧 if(S->count!=0) { Pop(S,p); //取出子樹根結點,因為以後訪問右子樹的時候已經不需要記錄根結點 Push(S,p->rchild); //右孩子入棧 } } } //非遞迴中序遍歷二叉樹1 void InOrderTraverse_nonRecursion(BiTree T) { StLink S; BiTree p; InitStack(S); Push(S,T); //根指標進棧 while(S->count!=0) { while(Getpop(S,p)&&p) Push(S,p->lchild); //向左走到盡頭 Pop(S,p); //空指標退棧 if(S->count!=0) { Pop(S,p); //取出子樹根結點,因為以後訪問右子樹的時候已經不需要記錄根結點 printf("%c",p->data); //訪問結點 Push(S,p->rchild); //右孩子入棧 } } } //非遞迴後序遍歷二叉樹1 void PostOrderTraverse_nonRecursion(BiTree T) { StLink S; BiTree p; int tag[100]={0};//標誌位,為0表示右子樹還沒遍歷,為1表示右子樹已經遍歷 InitStack(S); Push(S,T); //根指標進棧 while(S->count!=0) { while(Getpop(S,p)&&p) { Push(S,p->lchild); tag[S->count]=0;} //向左走到盡頭,同時設定標誌位 Pop(S,p); //空指標退棧 if(S->count!=0) { while(tag[S->count]==1) //迴圈把已經遍歷過右子樹的根結點都遍歷了 { Pop(S,p); printf("%c",p->data); } if(S->count==0) break; //如果已經遍歷完,就退出迴圈 //遍歷右子樹,先改變標誌位為,然後將棧頂結點右孩子壓棧,同時設定其標誌位 Getpop(S,p); tag[S->count]=1; p=p->rchild; Push(S,p); tag[S->count]=0; } } } //非遞迴先序遍歷二叉樹2 void PreOrderTraverse_nonRecursion2(BiTree T) { StLink S; BiTree p; InitStack(S); p=T; while(p||S->count!=0) { if(p) {Push(S,p); printf("%c",p->data); p=p->lchild;} else { Pop(S,p); p=p->rchild; } } } //非遞迴中序遍歷二叉樹2 void InOrderTraverse_nonRecursion2(BiTree T) { StLink S; BiTree p; InitStack(S); p=T; while(p||S->count!=0) { if(p) {Push(S,p); p=p->lchild;} else { Pop(S,p); printf("%c",p->data); p=p->rchild; } } } //非遞迴層次遍歷二叉樹,使用佇列先進先出 void FloorOrderTraverse_nonRecursion(BiTree T) { QuLink Q; BiTree p; InitQueue(Q); EnQueue(Q,T);//根結點入隊 while(Q->count!=0) { DeQueue(Q,p); printf("%c",p->data); if(p->lchild) EnQueue(Q,p->lchild); if(p->rchild) EnQueue(Q,p->rchild); } } //統計葉子結點個數 void CountLeaf(BiTree T,int &num) { if(T==NULL) return; if(T->lchild==NULL&&T->rchild==NULL) num++; //這裡也可以直接把葉子結點輸出 else { CountLeaf(T->lchild,num); CountLeaf(T->rchild,num); } } //計算二叉樹樹深度 int CalBiTreeDeep(BiTree T) { int deep=0; if(T==NULL) return 0; int dl=CalBiTreeDeep(T->lchild); int dr=CalBiTreeDeep(T->rchild); return 1+(dl>dr?dl:dr); } int _tmain(int argc, _TCHAR* argv[]) { BiTree T; int num=0; int deep; //printf("%s\n","請後序輸入二叉樹序列"); //PostCreateBiTree(T); printf("%s\n","請先序序輸入二叉樹序列"); PreCreateBiTree(T); printf("%s\n","非遞迴先序1輸出為:"); PreOrderTraverse_nonRecursion(T); puts("");//換行 printf("%s\n","非遞迴先序2輸出為:"); PreOrderTraverse_nonRecursion2(T); puts(""); printf("%s\n","非遞迴中序1輸出為:"); InOrderTraverse_nonRecursion(T); puts(""); printf("%s\n","非遞迴中序2輸出為:"); InOrderTraverse_nonRecursion2(T); puts(""); printf("%s\n","非遞迴後序輸出為:"); PostOrderTraverse_nonRecursion(T); puts(""); printf("%s\n","非遞迴按層次遍歷二叉樹輸出為:"); FloorOrderTraverse_nonRecursion(T); puts(""); CountLeaf(T,num); printf("%s%d\n","該二叉樹的葉子結點總數為:",num); deep=CalBiTreeDeep(T); printf("%s%d\n","該二叉樹的數深度為:",deep); return 0; }
輸入下圖表示的二叉樹:
執行結果為: