/* c6-5.h 樹的二叉鏈表(孩子-兄弟)存儲表示 */ typedef struct CSNode { TElemType data; struct CSNode *firstchild,*nextsibling; }CSNode,*CSTree;
/* bo6-5.c 樹的二叉鏈表(孩子-兄弟)存儲(存儲結構由c6-5.h定義)的基本操做(17個) */ Status InitTree(CSTree *T) { /* 操做結果: 構造空樹T */ *T=NULL; return OK; } void DestroyTree(CSTree *T) { /* 初始條件: 樹T存在。操做結果: 銷燬樹T */ if(*T) { if((*T)->firstchild) /* T有長子 */ DestroyTree(&(*T)->firstchild); /* 銷燬T的長子爲根結點的子樹 */ if((*T)->nextsibling) /* T有下一個兄弟 */ DestroyTree(&(*T)->nextsibling); /* 銷燬T的下一個兄弟爲根結點的子樹 */ free(*T); /* 釋放根結點 */ *T=NULL; } } typedef CSTree QElemType; /* 定義隊列元素類型 */ #include"c3-2.h" /* 定義LinkQueue類型 */ #include"bo3-2.c" /* LinkQueue類型的基本操做 */ Status CreateTree(CSTree *T) { /* 構造樹T */ char c[20]; /* 臨時存放孩子結點(設不超過20個)的值 */ CSTree p,p1; LinkQueue q; int i,l; InitQueue(&q); printf("請輸入根結點(字符型,空格爲空): "); scanf("%c%*c",&c[0]); if(c[0]!=Nil) /* 非空樹 */ { *T=(CSTree)malloc(sizeof(CSNode)); /* 創建根結點 */ (*T)->data=c[0]; (*T)->nextsibling=NULL; EnQueue(&q,*T); /* 入隊根結點的指針 */ while(!QueueEmpty(q)) /* 隊不空 */ { DeQueue(&q,&p); /* 出隊一個結點的指針 */ printf("請按長幼順序輸入結點%c的全部孩子: ",p->data); gets(c); l=strlen(c); if(l>0) /* 有孩子 */ { p1=p->firstchild=(CSTree)malloc(sizeof(CSNode)); /* 創建長子結點 */ p1->data=c[0]; for(i=1;i<l;i++) { p1->nextsibling=(CSTree)malloc(sizeof(CSNode)); /* 創建下一個兄弟結點 */ EnQueue(&q,p1); /* 入隊上一個結點 */ p1=p1->nextsibling; p1->data=c[i]; } p1->nextsibling=NULL; EnQueue(&q,p1); /* 入隊最後一個結點 */ } else p->firstchild=NULL; } } else *T=NULL; return OK; } #define ClearTree DestroyTree /* 兩者操做相同 */ Status TreeEmpty(CSTree T) { /* 初始條件: 樹T存在。操做結果: 若T爲空樹,則返回TURE,不然返回FALSE */ if(T) /* T不空 */ return FALSE; else return TRUE; } int TreeDepth(CSTree T) { /* 初始條件: 樹T存在。操做結果: 返回T的深度 */ CSTree p; int depth,max=0; if(!T) /* 樹空 */ return 0; if(!T->firstchild) /* 樹無長子 */ return 1; for(p=T->firstchild;p;p=p->nextsibling) { depth=TreeDepth(p); if(depth>max) max=depth; } return max+1; } TElemType Value(CSTree p) { /* 返回p所指結點的值 */ return p->data; } TElemType Root(CSTree T) { /* 初始條件: 樹T存在。操做結果: 返回T的根 */ if(T) return Value(T); else return Nil; } CSTree Point(CSTree T,TElemType s) { /* 返回二叉鏈表(孩子-兄弟)樹T中指向元素值爲s的結點的指針。另加 */ LinkQueue q; QElemType a; if(T) /* 非空樹 */ { InitQueue(&q); /* 初始化隊列 */ EnQueue(&q,T); /* 根結點入隊 */ while(!QueueEmpty(q)) /* 隊不空 */ { DeQueue(&q,&a); /* 出隊,隊列元素賦給a */ if(a->data==s) return a; if(a->firstchild) /* 有長子 */ EnQueue(&q,a->firstchild); /* 入隊長子 */ if(a->nextsibling) /* 有下一個兄弟 */ EnQueue(&q,a->nextsibling); /* 入隊下一個兄弟 */ } } return NULL; } Status Assign(CSTree *T,TElemType cur_e,TElemType value) { /* 初始條件: 樹T存在,cur_e是樹T中結點的值。操做結果: 改cur_e爲value */ CSTree p; if(*T) /* 非空樹 */ { p=Point(*T,cur_e); /* p爲cur_e的指針 */ if(p) /* 找到cur_e */ { p->data=value; /* 賦新值 */ return OK; } } return Nil; /* 樹空或沒找到 */ } TElemType Parent(CSTree T,TElemType cur_e) { /* 初始條件: 樹T存在,cur_e是T中某個結點 */ /* 操做結果: 若cur_e是T的非根結點,則返回它的雙親,不然函數值爲"空" */ CSTree p,t; LinkQueue q; InitQueue(&q); if(T) /* 樹非空 */ { if(Value(T)==cur_e) /* 根結點值爲cur_e */ return Nil; EnQueue(&q,T); /* 根結點入隊 */ while(!QueueEmpty(q)) { DeQueue(&q,&p); if(p->firstchild) /* p有長子 */ { if(p->firstchild->data==cur_e) /* 長子爲cur_e */ return Value(p); /* 返回雙親 */ t=p; /* 雙親指針賦給t */ p=p->firstchild; /* p指向長子 */ EnQueue(&q,p); /* 入隊長子 */ while(p->nextsibling) /* 有下一個兄弟 */ { p=p->nextsibling; /* p指向下一個兄弟 */ if(Value(p)==cur_e) /* 下一個兄弟爲cur_e */ return Value(t); /* 返回雙親 */ EnQueue(&q,p); /* 入隊下一個兄弟 */ } } } } return Nil; /* 樹空或沒找到cur_e */ } TElemType LeftChild(CSTree T,TElemType cur_e) { /* 初始條件: 樹T存在,cur_e是T中某個結點 */ /* 操做結果: 若cur_e是T的非葉子結點,則返回它的最左孩子,不然返回"空" */ CSTree f; f=Point(T,cur_e); /* f指向結點cur_e */ if(f&&f->firstchild) /* 找到結點cur_e且結點cur_e有長子 */ return f->firstchild->data; else return Nil; } TElemType RightSibling(CSTree T,TElemType cur_e) { /* 初始條件: 樹T存在,cur_e是T中某個結點 */ /* 操做結果: 若cur_e有右兄弟,則返回它的右兄弟,不然返回"空" */ CSTree f; f=Point(T,cur_e); /* f指向結點cur_e */ if(f&&f->nextsibling) /* 找到結點cur_e且結點cur_e有右兄弟 */ return f->nextsibling->data; else return Nil; /* 樹空 */ } Status InsertChild(CSTree *T,CSTree p,int i,CSTree c) { /* 初始條件: 樹T存在,p指向T中某個結點,1≤i≤p所指結點的度+1,非空樹c與T不相交 */ /* 操做結果: 插入c爲T中p結點的第i棵子樹 */ /* 由於p所指結點的地址不會改變,故p不需是引用類型 */ int j; if(*T) /* T不空 */ { if(i==1) /* 插入c爲p的長子 */ { c->nextsibling=p->firstchild; /* p的原長子現是c的下一個兄弟(c本無兄弟) */ p->firstchild=c; } else /* 找插入點 */ { p=p->firstchild; /* 指向p的長子 */ j=2; while(p&&j<i) { p=p->nextsibling; j++; } if(j==i) /* 找到插入位置 */ { c->nextsibling=p->nextsibling; p->nextsibling=c; } else /* p原有孩子數小於i-1 */ return ERROR; } return OK; } else /* T空 */ return ERROR; } Status DeleteChild(CSTree *T,CSTree p,int i) { /* 初始條件: 樹T存在,p指向T中某個結點,1≤i≤p所指結點的度 */ /* 操做結果: 刪除T中p所指結點的第i棵子樹 */ /* 由於p所指結點的地址不會改變,故p不需是引用類型 */ CSTree b; int j; if(*T) /* T不空 */ { if(i==1) /* 刪除長子 */ { b=p->firstchild; p->firstchild=b->nextsibling; /* p的原次子現是長子 */ b->nextsibling=NULL; DestroyTree(&b); } else /* 刪除非長子 */ { p=p->firstchild; /* p指向長子 */ j=2; while(p&&j<i) { p=p->nextsibling; j++; } if(j==i) /* 找到第i棵子樹 */ { b=p->nextsibling; p->nextsibling=b->nextsibling; b->nextsibling=NULL; DestroyTree(&b); } else /* p原有孩子數小於i */ return ERROR; } return OK; } else return ERROR; } void PreOrderTraverse(CSTree T,void(*Visit)(TElemType)) { /* 先根遍歷孩子-兄弟二叉鏈表結構的樹T */ if(T) { Visit(Value(T)); /* 先訪問根結點 */ PreOrderTraverse(T->firstchild,Visit); /* 再先根遍歷長子子樹 */ PreOrderTraverse(T->nextsibling,Visit); /* 最後先根遍歷下一個兄弟子樹 */ } } void PostOrderTraverse(CSTree T,void(*Visit)(TElemType)) { /* 後根遍歷孩子-兄弟二叉鏈表結構的樹T */ CSTree p; if(T) { if(T->firstchild) /* 有長子 */ { PostOrderTraverse(T->firstchild,Visit); /* 後根遍歷長子子樹 */ p=T->firstchild->nextsibling; /* p指向長子的下一個兄弟 */ while(p) { PostOrderTraverse(p,Visit); /* 後根遍歷下一個兄弟子樹 */ p=p->nextsibling; /* p指向再下一個兄弟 */ } } Visit(Value(T)); /* 最後訪問根結點 */ } } void LevelOrderTraverse(CSTree T,void(*Visit)(TElemType)) { /* 層序遍歷孩子-兄弟二叉鏈表結構的樹T */ CSTree p; LinkQueue q; InitQueue(&q); if(T) { Visit(Value(T)); /* 先訪問根結點 */ EnQueue(&q,T); /* 入隊根結點的指針 */ while(!QueueEmpty(q)) /* 隊不空 */ { DeQueue(&q,&p); /* 出隊一個結點的指針 */ if(p->firstchild) /* 有長子 */ { p=p->firstchild; Visit(Value(p)); /* 訪問長子結點 */ EnQueue(&q,p); /* 入隊長子結點的指針 */ while(p->nextsibling) /* 有下一個兄弟 */ { p=p->nextsibling; Visit(Value(p)); /* 訪問下一個兄弟 */ EnQueue(&q,p); /* 入隊兄弟結點的指針 */ } } } } }
/* main6-5.c 檢驗bo6-5.c的主程序 */ #include"c1.h" typedef char TElemType; TElemType Nil=' '; /* 以空格符爲空 */ #include"c6-5.h" #include"bo6-5.c" void vi(TElemType c) { printf("%c ",c); } void main() { int i; CSTree T,p,q; TElemType e,e1; InitTree(&T); printf("構造空樹後,樹空否? %d(1:是 0:否) 樹根爲%c 樹的深度爲%d\n",TreeEmpty(T),Root(T),TreeDepth(T)); CreateTree(&T); printf("構造樹T後,樹空否? %d(1:是 0:否) 樹根爲%c 樹的深度爲%d\n",TreeEmpty(T),Root(T),TreeDepth(T)); printf("先根遍歷樹T:\n"); PreOrderTraverse(T,vi); printf("\n請輸入待修改的結點的值 新值: "); scanf("%c%*c%c%*c",&e,&e1); Assign(&T,e,e1); printf("後根遍歷修改後的樹T:\n"); PostOrderTraverse(T,vi); printf("\n%c的雙親是%c,長子是%c,下一個兄弟是%c\n",e1,Parent(T,e1),LeftChild(T,e1),RightSibling(T,e1)); printf("創建樹p:\n"); InitTree(&p); CreateTree(&p); printf("層序遍歷樹p:\n"); LevelOrderTraverse(p,vi); printf("\n將樹p插到樹T中,請輸入T中p的雙親結點 子樹序號: "); scanf("%c%d%*c",&e,&i); q=Point(T,e); InsertChild(&T,q,i,p); printf("層序遍歷樹T:\n"); LevelOrderTraverse(T,vi); printf("\n刪除樹T中結點e的第i棵子樹,請輸入e i: "); scanf("%c%d",&e,&i); q=Point(T,e); DeleteChild(&T,q,i); printf("層序遍歷樹T:\n",e,i); LevelOrderTraverse(T,vi); printf("\n"); DestroyTree(&T); }