/* c6-1.h 二叉樹的順序存儲表示 */ #define MAX_TREE_SIZE 100 /* 二叉樹的最大結點數 */ typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0號單元存儲根結點 */ typedef struct { int level,order; /* 結點的層,本層序號(按滿二叉樹計算) */ }position;
/* bo6-1.c 二叉樹的順序存儲(存儲結構由c6-1.h定義)的基本操做(23個) */ Status InitBiTree(SqBiTree T) { /* 構造空二叉樹T。由於T是固定數組,不會改變,故不須要& */ int i; for(i=0;i<MAX_TREE_SIZE;i++) T[i]=Nil; /* 初值爲空 */ return OK; } void DestroyBiTree() { /* 因爲SqBiTree是定長類型,沒法銷燬 */ } Status CreateBiTree(SqBiTree T) { /* 按層序次序輸入二叉樹中結點的值(字符型或整型), 構造順序存儲的二叉樹T */ int i=0; #if CHAR int l; char s[MAX_TREE_SIZE]; printf("請按層序輸入結點的值(字符),空格表示空結點,結點數≤%d:\n",MAX_TREE_SIZE); gets(s); /* 輸入字符串 */ l=strlen(s); /* 求字符串的長度 */ for(;i<l;i++) /* 將字符串賦值給T */ { T[i]=s[i]; if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此結點(不空)無雙親且不是根 */ { printf("出現無雙親的非根結點%c\n",T[i]); exit(ERROR); } } for(i=l;i<MAX_TREE_SIZE;i++) /* 將空賦值給T的後面的結點 */ T[i]=Nil; #else printf("請按層序輸入結點的值(整型),0表示空結點,輸999結束。結點數≤%d:\n",MAX_TREE_SIZE); while(1) { scanf("%d",&T[i]); if(T[i]==999) break; if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此結點(不空)無雙親且不是根 */ { printf("出現無雙親的非根結點%d\n",T[i]); exit(ERROR); } i++; } while(i<MAX_TREE_SIZE) { T[i]=Nil; /* 將空賦值給T的後面的結點 */ i++; } #endif return OK; } #define ClearBiTree InitBiTree /* 在順序存儲結構中,兩函數徹底同樣 */ Status BiTreeEmpty(SqBiTree T) { /* 初始條件: 二叉樹T存在 */ /* 操做結果: 若T爲空二叉樹,則返回TRUE,不然FALSE */ if(T[0]==Nil) /* 根結點爲空,則樹空 */ return TRUE; else return FALSE; } int BiTreeDepth(SqBiTree T) { /* 初始條件: 二叉樹T存在。操做結果: 返回T的深度 */ int i,j=-1; for(i=MAX_TREE_SIZE-1;i>=0;i--) /* 找到最後一個結點 */ if(T[i]!=Nil) break; i++; /* 爲了便於計算 */ do j++; while(i>=pow(2,j)); return j; } Status Root(SqBiTree T,TElemType *e) { /* 初始條件: 二叉樹T存在 */ /* 操做結果: 當T不空,用e返回T的根,返回OK;不然返回ERROR,e無定義 */ if(BiTreeEmpty(T)) /* T空 */ return ERROR; else { *e=T[0]; return OK; } } TElemType Value(SqBiTree T,position e) { /* 初始條件: 二叉樹T存在,e是T中某個結點(的位置) */ /* 操做結果: 返回處於位置e(層,本層序號)的結點的值 */ return T[(int)pow(2,e.level-1)+e.order-2]; } Status Assign(SqBiTree T,position e,TElemType value) { /* 初始條件: 二叉樹T存在,e是T中某個結點(的位置) */ /* 操做結果: 給處於位置e(層,本層序號)的結點賦新值value */ int i=(int)pow(2,e.level-1)+e.order-2; /* 將層、本層序號轉爲矩陣的序號 */ if(value!=Nil&&T[(i+1)/2-1]==Nil) /* 給葉子賦非空值但雙親爲空 */ return ERROR; else if(value==Nil&&(T[i*2+1]!=Nil||T[i*2+2]!=Nil)) /* 給雙親賦空值但有葉子(不空) */ return ERROR; T[i]=value; return OK; } TElemType Parent(SqBiTree T,TElemType e) { /* 初始條件: 二叉樹T存在,e是T中某個結點 */ /* 操做結果: 若e是T的非根結點,則返回它的雙親,不然返回"空" */ int i; if(T[0]==Nil) /* 空樹 */ return Nil; for(i=1;i<=MAX_TREE_SIZE-1;i++) if(T[i]==e) /* 找到e */ return T[(i+1)/2-1]; return Nil; /* 沒找到e */ } TElemType LeftChild(SqBiTree T,TElemType e) { /* 初始條件: 二叉樹T存在,e是T中某個結點 */ /* 操做結果: 返回e的左孩子。若e無左孩子,則返回"空" */ int i; if(T[0]==Nil) /* 空樹 */ return Nil; for(i=0;i<=MAX_TREE_SIZE-1;i++) if(T[i]==e) /* 找到e */ return T[i*2+1]; return Nil; /* 沒找到e */ } TElemType RightChild(SqBiTree T,TElemType e) { /* 初始條件: 二叉樹T存在,e是T中某個結點 */ /* 操做結果: 返回e的右孩子。若e無右孩子,則返回"空" */ int i; if(T[0]==Nil) /* 空樹 */ return Nil; for(i=0;i<=MAX_TREE_SIZE-1;i++) if(T[i]==e) /* 找到e */ return T[i*2+2]; return Nil; /* 沒找到e */ } TElemType LeftSibling(SqBiTree T,TElemType e) { /* 初始條件: 二叉樹T存在,e是T中某個結點 */ /* 操做結果: 返回e的左兄弟。若e是T的左孩子或無左兄弟,則返回"空" */ int i; if(T[0]==Nil) /* 空樹 */ return Nil; for(i=1;i<=MAX_TREE_SIZE-1;i++) if(T[i]==e&&i%2==0) /* 找到e且其序號爲偶數(是右孩子) */ return T[i-1]; return Nil; /* 沒找到e */ } TElemType RightSibling(SqBiTree T,TElemType e) { /* 初始條件: 二叉樹T存在,e是T中某個結點 */ /* 操做結果: 返回e的右兄弟。若e是T的右孩子或無右兄弟,則返回"空" */ int i; if(T[0]==Nil) /* 空樹 */ return Nil; for(i=1;i<=MAX_TREE_SIZE-1;i++) if(T[i]==e&&i%2) /* 找到e且其序號爲奇數(是左孩子) */ return T[i+1]; return Nil; /* 沒找到e */ } void Move(SqBiTree q,int j,SqBiTree T,int i) /* InsertChild()用到。加 */ { /* 把從q的j結點開始的子樹移爲從T的i結點開始的子樹 */ if(q[2*j+1]!=Nil) /* q的左子樹不空 */ Move(q,(2*j+1),T,(2*i+1)); /* 把q的j結點的左子樹移爲T的i結點的左子樹 */ if(q[2*j+2]!=Nil) /* q的右子樹不空 */ Move(q,(2*j+2),T,(2*i+2)); /* 把q的j結點的右子樹移爲T的i結點的右子樹 */ T[i]=q[j]; /* 把q的j結點移爲T的i結點 */ q[j]=Nil; /* 把q的j結點置空 */ } Status InsertChild(SqBiTree T,TElemType p,Status LR,SqBiTree c) { /* 初始條件: 二叉樹T存在,p是T中某個結點的值,LR爲0或1,非空二叉樹c與T */ /* 不相交且右子樹爲空 */ /* 操做結果: 根據LR爲0或1,插入c爲T中p結點的左或右子樹。p結點的原有左或 */ /* 右子樹則成爲c的右子樹 */ int j,k,i=0; for(j=0;j<(int)pow(2,BiTreeDepth(T))-1;j++) /* 查找p的序號 */ if(T[j]==p) /* j爲p的序號 */ break; k=2*j+1+LR; /* k爲p的左或右孩子的序號 */ if(T[k]!=Nil) /* p原來的左或右孩子不空 */ Move(T,k,T,2*k+2); /* 把從T的k結點開始的子樹移爲從k結點的右子樹開始的子樹 */ Move(c,i,T,k); /* 把從c的i結點開始的子樹移爲從T的k結點開始的子樹 */ return OK; } typedef int QElemType; /* 設隊列元素類型爲整型(序號) */ #include "c3-3.h" /* 順序非循環隊列 */ #include "bo3-4.c" /* 順序非循環隊列的基本操做 */ Status DeleteChild(SqBiTree T,position p,int LR) { /* 初始條件: 二叉樹T存在,p指向T中某個結點,LR爲1或0 */ /* 操做結果: 根據LR爲1或0,刪除T中p所指結點的左或右子樹 */ int i; Status k=OK; /* 隊列不空的標誌 */ SqQueue q; InitQueue(&q); /* 初始化隊列,用於存放待刪除的結點 */ i=(int)pow(2,p.level-1)+p.order-2; /* 將層、本層序號轉爲矩陣的序號 */ if(T[i]==Nil) /* 此結點空 */ return ERROR; i=i*2+1+LR; /* 待刪除子樹的根結點在矩陣中的序號 */ while(k) { if(T[2*i+1]!=Nil) /* 左結點不空 */ EnQueue(&q,2*i+1); /* 入隊左結點的序號 */ if(T[2*i+2]!=Nil) /* 右結點不空 */ EnQueue(&q,2*i+2); /* 入隊右結點的序號 */ T[i]=Nil; /* 刪除此結點 */ k=DeQueue(&q,&i); /* 隊列不空 */ } return OK; } Status(*VisitFunc)(TElemType); /* 函數變量 */ void PreTraverse(SqBiTree T,int e) { /* PreOrderTraverse()調用 */ VisitFunc(T[e]); if(T[2*e+1]!=Nil) /* 左子樹不空 */ PreTraverse(T,2*e+1); if(T[2*e+2]!=Nil) /* 右子樹不空 */ PreTraverse(T,2*e+2); } Status PreOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 初始條件: 二叉樹存在,Visit是對結點操做的應用函數 */ /* 操做結果: 先序遍歷T,對每一個結點調用函數Visit一次且僅一次。 */ /* 一旦Visit()失敗,則操做失敗 */ VisitFunc=Visit; if(!BiTreeEmpty(T)) /* 樹不空 */ PreTraverse(T,0); printf("\n"); return OK; } void InTraverse(SqBiTree T,int e) { /* InOrderTraverse()調用 */ if(T[2*e+1]!=Nil) /* 左子樹不空 */ InTraverse(T,2*e+1); VisitFunc(T[e]); if(T[2*e+2]!=Nil) /* 右子樹不空 */ InTraverse(T,2*e+2); } Status InOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 初始條件: 二叉樹存在,Visit是對結點操做的應用函數 */ /* 操做結果: 中序遍歷T,對每一個結點調用函數Visit一次且僅一次。 */ /* 一旦Visit()失敗,則操做失敗 */ VisitFunc=Visit; if(!BiTreeEmpty(T)) /* 樹不空 */ InTraverse(T,0); printf("\n"); return OK; } void PostTraverse(SqBiTree T,int e) { /* PostOrderTraverse()調用 */ if(T[2*e+1]!=Nil) /* 左子樹不空 */ PostTraverse(T,2*e+1); if(T[2*e+2]!=Nil) /* 右子樹不空 */ PostTraverse(T,2*e+2); VisitFunc(T[e]); } Status PostOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 初始條件: 二叉樹T存在,Visit是對結點操做的應用函數 */ /* 操做結果: 後序遍歷T,對每一個結點調用函數Visit一次且僅一次。 */ /* 一旦Visit()失敗,則操做失敗 */ VisitFunc=Visit; if(!BiTreeEmpty(T)) /* 樹不空 */ PostTraverse(T,0); printf("\n"); return OK; } void LevelOrderTraverse(SqBiTree T,Status(*Visit)(TElemType)) { /* 層序遍歷二叉樹 */ int i=MAX_TREE_SIZE-1,j; while(T[i]==Nil) i--; /* 找到最後一個非空結點的序號 */ for(j=0;j<=i;j++) /* 從根結點起,按層序遍歷二叉樹 */ if(T[j]!=Nil) Visit(T[j]); /* 只遍歷非空的結點 */ printf("\n"); } void Print(SqBiTree T) { /* 逐層、按本層序號輸出二叉樹 */ int j,k; position p; TElemType e; for(j=1;j<=BiTreeDepth(T);j++) { printf("第%d層: ",j); for(k=1;k<=pow(2,j-1);k++) { p.level=j; p.order=k; e=Value(T,p); if(e!=Nil) printf("%d:%d ",k,e); } printf("\n"); } }
/* main6-1.c 檢驗bo6-1.c的主程序,利用條件編譯選擇數據類型爲char或int */ /*#define CHAR 1 /* 字符型 */ #define CHAR 0 /* 整型(兩者選一) */ #include"c1.h" #if CHAR typedef char TElemType; TElemType Nil=' '; /* 設字符型以空格符爲空 */ #else typedef int TElemType; TElemType Nil=0; /* 設整型以0爲空 */ #endif #include"c6-1.h" #include"bo6-1.c" Status visit(TElemType e) { printf("%d ",e); return OK; } void main() { Status i; int j; position p; TElemType e; SqBiTree T,s; InitBiTree(T); CreateBiTree(T); printf("創建二叉樹後,樹空否?%d(1:是 0:否) 樹的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T)); i=Root(T,&e); if(i) printf("二叉樹的根爲:%d\n",e); else printf("樹空,無根\n"); printf("層序遍歷二叉樹:\n"); LevelOrderTraverse(T,visit); printf("中序遍歷二叉樹:\n"); InOrderTraverse(T,visit); printf("後序遍歷二叉樹:\n"); PostOrderTraverse(T,visit); printf("請輸入待修改結點的層號 本層序號: "); scanf("%d%d",&p.level,&p.order); e=Value(T,p); printf("待修改結點的原值爲%d請輸入新值: ",e); scanf("%d",&e); Assign(T,p,e); printf("先序遍歷二叉樹:\n"); PreOrderTraverse(T,visit); printf("結點%d的雙親爲%d,左右孩子分別爲",e,Parent(T,e)); printf("%d,%d,左右兄弟分別爲",LeftChild(T,e),RightChild(T,e)); printf("%d,%d\n",LeftSibling(T,e),RightSibling(T,e)); InitBiTree(s); printf("創建右子樹爲空的樹s:\n"); CreateBiTree(s); printf("樹s插到樹T中,請輸入樹T中樹s的雙親結點 s爲左(0)或右(1)子樹: "); scanf("%d%d",&e,&j); InsertChild(T,e,j,s); Print(T); printf("刪除子樹,請輸入待刪除子樹根結點的層號 本層序號 左(0)或右(1)子樹: "); scanf("%d%d%d",&p.level,&p.order,&j); DeleteChild(T,p,j); Print(T); ClearBiTree(T); printf("清除二叉樹後,樹空否?%d(1:是 0:否) 樹的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T)); i=Root(T,&e); if(i) printf("二叉樹的根爲:%d\n",e); else printf("樹空,無根\n"); }