廣義表的複製及C語言程式碼實現
阿新 • • 發佈:2018-12-23
對於任意一個非空廣義表來說,都是由兩部分組成:表頭和表尾。反之,只要確定的一個廣義表的表頭和表尾,那麼這個廣義表就可以唯一確定下來。
複製一個廣義表,也是不斷的複製表頭和表尾的過程。如果表頭或者表尾同樣是一個廣義表,依舊複製其表頭和表尾。
所以,複製廣義表的過程,其實就是不斷的遞迴,複製廣義表中表頭和表尾的過程。
遞迴的出口有兩個:
還拿廣義表C為例:
圖1 廣義表C的結構示意圖
程式碼實現:
執行結果:
a
這裡使用的是地址傳遞,而不是值傳遞。如果在這裡使用值傳遞,會導致廣義表 T 丟失結點,複製失敗。
複製一個廣義表,也是不斷的複製表頭和表尾的過程。如果表頭或者表尾同樣是一個廣義表,依舊複製其表頭和表尾。
所以,複製廣義表的過程,其實就是不斷的遞迴,複製廣義表中表頭和表尾的過程。
遞迴的出口有兩個:
- 如果當前遍歷的資料元素為空表,則直接返回空表。
- 如果當前遍歷的資料元素為該表的一個原子,那麼直接複製,返回即可。
還拿廣義表C為例:
圖1 廣義表C的結構示意圖
程式碼實現:
#include <stdio.h> #include <stdlib.h> typedef struct GLNode{ int tag;//標誌域 union{ char atom;//原子結點的值域 struct{ struct GLNode * hp,*tp; }ptr;//子表結點的指標域,hp指向表頭;tp指向表尾 }; }*Glist,GNode; Glist creatGlist(Glist C){ //廣義表C C=(Glist)malloc(sizeof(GNode)); C->tag=1; //表頭原子‘a’ C->ptr.hp=(Glist)malloc(sizeof(GNode)); C->ptr.hp->tag=0; C->ptr.hp->atom='a'; //表尾子表(b,c,d),是一個整體 C->ptr.tp=(Glist)malloc(sizeof(GNode)); C->ptr.tp->tag=1; C->ptr.tp->ptr.hp=(Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.tp=NULL; //開始存放下一個資料元素(b,c,d),表頭為‘b’,表尾為(c,d) C->ptr.tp->ptr.hp->tag=1; C->ptr.tp->ptr.hp->ptr.hp=(Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.hp->tag=0; C->ptr.tp->ptr.hp->ptr.hp->atom='b'; C->ptr.tp->ptr.hp->ptr.tp=(Glist)malloc(sizeof(GNode)); //存放子表(c,d),表頭為c,表尾為d C->ptr.tp->ptr.hp->ptr.tp->tag=1; C->ptr.tp->ptr.hp->ptr.tp->ptr.hp=(Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->tag=0; C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->atom='c'; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp=(Glist)malloc(sizeof(GNode)); //存放表尾d C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->tag=1; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp=(Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->tag=0; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->atom='d'; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.tp=NULL; return C; } void copyGlist(Glist C, Glist *T){ //如果C為空表,那麼複製表直接為空表 if (!C) { *T=NULL; } else{ *T=(Glist)malloc(sizeof(GNode));//C不是空表,給T申請記憶體空間 //申請失敗,程式停止 if (!*T) { exit(0); } (*T)->tag=C->tag;//複製表C的tag值 //判斷當前表元素是否為原子,如果是,直接複製 if (C->tag==0) { (*T)->atom=C->atom; }else{//執行到這,說明覆制的是子表 copyGlist(C->ptr.hp, &((*T)->ptr.hp));//複製表頭 copyGlist(C->ptr.tp, &((*T)->ptr.tp));//複製表尾 } } } int main(int argc, const char * argv[]) { Glist C=NULL; C=creatGlist(C); Glist T=NULL; copyGlist(C,&T); printf("%c",T->ptr.hp->atom); return 0; }
總結
在實現複製廣義表的過程中,實現函式為: void copyGlist(Glist C, Glist *T); 其中,Glist *T,等同於: struct GLNode* *T,此為二級指標,不是一級指標。在主函式中,呼叫此函式時,傳入的是指標 T 的地址,而不是 T 。這裡使用的是地址傳遞,而不是值傳遞。如果在這裡使用值傳遞,會導致廣義表 T 丟失結點,複製失敗。