數據結構之---C語言實現廣義表頭尾鏈表存儲表示
//廣義表的頭尾鏈表存儲表示 //楊鑫 #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <string.h> #define MAXSTRLEN 40 ) typedef char SString[MAXSTRLEN+1]; typedef char AtomType; // 定義原子類型為字符型 typedef enum{ ATOM, LIST // ATOM==0:原子 LIST==1:子表 } ElemTag; typedef struct GLNode { ElemTag tag; // 公共部分,用於區分原子結點和表結點 union // 原子結點和表結點的聯合部分 { AtomType atom; // atom是原子結點的值域, AtomType由用戶定義 struct { struct GLNode *hp,*tp; }ptr; // ptr是表結點的指針域,prt.hp和ptr.tp分別指向表頭和表尾 }a; } *GList, GLNode; //初始化的廣義表L int InitGList(GList *L) { *L = NULL; return 1; } //銷毀廣義表L void DestroyGList(GList *L) { GList q1,q2; if(*L) { if((*L)->tag == ATOM) { free(*L); *L = NULL; } else { q1 = (*L)->a.ptr.hp; q2 = (*L)->a.ptr.tp; free(*L); *L = NULL; DestroyGList(&q1); DestroyGList(&q2); // 遞歸刪除表頭和表尾結點 } } } // 採用頭尾鏈表存儲結構,由廣義表L復制得到廣義表T。 int CopyGList(GList *T,GList L) { if(!L) *T = NULL; else { *T = (GList)malloc(sizeof(GLNode)); if(!*T) exit(0); (*T)->tag = L->tag; if(L->tag == ATOM) (*T)->a.atom = L->a.atom; // 復制單原子 else // 是表結點,則依次復制表頭和表尾 { CopyGList(&((*T)->a.ptr.hp), L->a.ptr.hp); CopyGList(&((*T)->a.ptr.tp), L->a.ptr.tp); } } return 1; } // 返回廣義表的長度,即元素個數 int GListLength(GList L) { int len = 0; if(!L) return 0; if(L->tag == ATOM) return 1; while(L) { L = L->a.ptr.tp; len++; } return len; } // 採用頭尾鏈表存儲結構,求廣義表L的深度。int GListDepth(GList L) { int max, dep; GList pp; if(!L) return 1; // 空表深度為1 if(L->tag == ATOM) return 0; // 原子深度為0 for(max = 0, pp = L; pp; pp = pp->a.ptr.tp) { // 遞歸求以pp->a.ptr.hp為頭指針的子表深度 dep = GListDepth(pp->a.ptr.hp); if(dep > max) max = dep; } return max+1; // 非空表的深度是各元素的深度的最大值加1 } // 判定廣義表是否為空 int GListEmpty(GList L) { if(!L) return 1; else return 0; } // 取廣義表L的頭 GList GetHead(GList L) { GList h,p; if(!L) { printf("空表無表頭!\n"); exit(0); } p = L->a.ptr.tp; L->a.ptr.tp = NULL; CopyGList(&h,L); L->a.ptr.tp = p; return h; } // 取廣義表L的尾 GList GetTail(GList L) { GList t; if(!L) { printf("空表無表尾!\n"); exit(0); } CopyGList(&t, L->a.ptr.tp); return t; } // 插入元素e作為廣義表L的第一元素(表頭,也可能是子表) int InsertFirst_GL(GList *L,GList e) { GList p = (GList)malloc(sizeof(GLNode)); if(!p) exit(0); p->tag = LIST; p->a.ptr.hp = e; p->a.ptr.tp = *L; *L = p; return 1; } // 刪除廣義表L的第一元素,並用e返回其值 int DeleteFirst_GL(GList *L,GList *e) { GList p; *e = (*L)->a.ptr.hp; p = *L; *L = (*L)->a.ptr.tp; free(p); return 1; } // 利用遞歸算法遍歷廣義表L void Traverse_GL(GList L,void(*v)(AtomType)) { if(L) if(L->tag == ATOM) v(L->a.atom); else { Traverse_GL(L->a.ptr.hp,v); Traverse_GL(L->a.ptr.tp,v); } } // 生成一個其值等於chars的串T int StrAssign(SString T,char *chars) { int i; if(strlen(chars) > MAXSTRLEN) return 0; else { T[0] = strlen(chars); for(i = 1; i <= T[0]; i++) T[i] = *(chars + i - 1); return 1; } } // 由串S復制得串T int StrCopy(SString T, SString S) { int i; for(i = 0; i <= S[0]; i++) T[i] = S[i]; return 1; } // 若S為空串,則返回1,否則返回0 int StrEmpty(SString S) { if(S[0] == 0) return 1; else return 0; } // 若S>T,則返回值>0;若S=T,則返回值=0;若S<T,則返回值<0 int StrCompare(SString S,SString T) { int i; for(i = 1; i <= S[0] && i <= T[0]; ++i) if(S[i] != T[i]) return S[i] - T[i]; return S[0]-T[0]; } // 返回串的元素個數 int StrLength(SString S) { return S[0]; } // 將S清為空串 int ClearString(SString S) { S[0] = 0; // 令串長為零 return 1; } // 用Sub返回串S的第pos個字符起長度為len的子串。 int SubString(SString Sub,SString S,int pos,int len) { int i; if(pos < 1 || pos >S[0] || len < 0 || len > S[0]-pos+1) return 0; for(i = 1; i <= len; i++) Sub[i]=S[pos+i-1]; Sub[0] = len; return 1; } // 將非空串str切割成兩部分:hsub為第一個‘,‘之前的子串,str為之後的子串 void sever(SString str,SString hstr) { int n,i, k; SString ch,c1,c2,c3; n = StrLength(str); StrAssign(c1,","); StrAssign(c2,"("); StrAssign(c3,")"); SubString(ch,str,1,1); for(i = 1,k = 0;i <= n && StrCompare(ch,c1) || k != 0; ++i) { SubString(ch, str, i, 1); if(!StrCompare(ch, c2)) ++k; else if(!StrCompare(ch,c3)) --k; } if(i <= n) { SubString(hstr, str, 1, i-2); SubString(str, str, i, n - i + 1); } else { StrCopy(hstr, str); ClearString(str); } } // 廣義表L。設emp="()" int CreateGList(GList *L, SString S) { SString sub,hsub,emp; GList p,q; StrAssign(emp,"()"); if(!StrCompare(S, emp)) *L = NULL; // 創建空表 else { *L = (GList)malloc(sizeof(GLNode)); if(!*L) // 建表結點 exit(0); if(StrLength(S) == 1) // S為單原子 { (*L)->tag = ATOM; (*L)->a.atom = S[1]; // 創建單原子廣義表 } else { (*L)->tag = LIST; p = *L; SubString(sub, S, 2, StrLength(S)-2); // 脫外層括號 do { // 反復建n個子表 sever(sub, hsub); // 從sub中分離出表頭串hsub CreateGList(&p->a. ptr. hp, hsub); q = p; if(!StrEmpty(sub)) // 表尾不空 { p = (GLNode *)malloc(sizeof(GLNode)); if(!p) exit(0); p->tag = LIST; q->a.ptr.tp = p; } }while(!StrEmpty(sub)); q->a.ptr.tp = NULL; } } return 1; } // 打印原子 void visit(AtomType e) { printf("%c ", e); } int main() { // 廣義表的表示形式是,空表:(),單原子:a,表:(a,(b),c,(d,(e))) char p[80] = {"(a,(b),c,(d,(e)))"}; SString t; GList L,m; InitGList(&L); InitGList(&m); printf("空廣義表L的深度 = %d\nL是否空?%d(1:是 0:否)\n\n", GListDepth(L), GListEmpty(L)); StrAssign(t, p); CreateGList(&L, t); // 創建廣義表 printf("\n廣義表L的長度 = %d\n", GListLength(L)); printf("廣義表L的深度 = %d \nL是否空?%d(1:是 0:否)\n", GListDepth(L), GListEmpty(L)); printf("遍歷廣義表L:\n"); Traverse_GL(L, visit); printf("\n\n復制廣義表m = L\n"); CopyGList(&m, L); printf("廣義表m的長度 = %d\n", GListLength(m)); printf("廣義表m的深度 = %d\n", GListDepth(m)); printf("遍歷廣義表m:\n"); Traverse_GL(m,visit); DestroyGList(&m); m = GetHead(L); printf("\n\nm是L的表頭,遍歷廣義表m:\n"); Traverse_GL(m, visit); DestroyGList(&m); m = GetTail(L); printf("\n\nm是L的表尾,遍歷廣義表m:\n"); Traverse_GL(m,visit); InsertFirst_GL(&m, L); printf("\n\n插入L為m的表頭。遍歷廣義表m:\n"); Traverse_GL(m,visit); printf("\n\n刪除m的表頭。遍歷廣義表m:\n"); DestroyGList(&L); DeleteFirst_GL(&m, &L); Traverse_GL(m, visit); printf("\n"); DestroyGList(&m); return 0; }
數據結構之---C語言實現廣義表頭尾鏈表存儲表示