書中的例子是,在多座島嶼間規劃航線,並記錄,將島嶼做爲節點,數據結構以下node
typedef struct island { char *name; char *opens; char *closes; struct island *next; } island;
注意,遞歸結構(含有指向相同類型的指針)不能爲匿名結構,結構中相同類型的指針,在c語法中不容許經過別名來聲明它。git
建立create,display,release函數
github
create:數據結構
island *create(char *name) { island *i = malloc(sizeof(island)); i->name = strdup(name); i->opens = "09:00"; i->closes = "17:00"; i->next = NULL; return i; }
分配sizeof(island)大小的堆內存,並將地址給i,malloc的返回值是void*類型,能夠充當任何類型指針賦值操做的右值,可是有的編譯器可能會警告。函數
給成員賦值:i->name=strdup(name);strdup的含義是在內存中拷貝name,並返回地址,返回值類型爲char* ,之因此這麼作,是由於name只是用作接收輸入的字符串,在內存中的位置固定,且內容會不斷更新,若是直接使用name,那麼就會有多個節點(i->name)指向同一個地址,結果就是,多個島嶼的名字都是最後一次輸入的那個。spa
i->next=NULL;因爲建立島嶼時不知道航線的下一個目的地是哪,因此邏輯上要置空,還有一個緣由就是,若是不把指針置爲NULL,那麼指向的內存位置是不肯定的,容易致使意想不到的問題。指針
display:code
void display(island *start) { island *i = start; for (; i != NULL; i = i->next) printf("Name:%s\n open:%s-%s\n", i->name, i->opens, i->closes); }
將鏈表(航線)的起始指針傳入,使用一個island類型的指針進行遍歷,這個指針充當的是遊標/迭代器。
遞歸
release:釋放內存內存
void release(island *start) { island *i = start; island *next = NULL; for (; i != NULL; i = next) { next = i->next; free(i->name); free(i); } printf("finish releasing.\n"); }
使用兩個island類型指針從起始位置開始進行順序釋放。邏輯步驟:將i指向起始位置,若是i指向的位置的next不爲空,next指向起始節點的下一個節點,釋放i,將i指向next指向的位置,而後循環。
free()接收一個void*指針,返回值類型爲void,注意一點:free(i)以前,要先把i->name釋放掉,還記得嗎,咱們用strdup拷貝的name,若是直接free(i),那麼拷貝的這個name的那部份內存,就再也訪問不到了,沒有人知道他的地址,形成內存泄漏,free函數並無那麼智能,因此咱們要手動的將這部份內存釋放掉,而後再free(i)。
main函數:
int main() { printf("Game on\n"); island *start = NULL; //i as a iterator island *i = NULL; island *node = NULL; char name[80]; for (; fgets(name, 80, stdin); i = node) { if (name[strlen(name) - 1] == '\n') name[strlen(name) - 1] = 0; //node leads to a piece of storage which contains the new island,the 'node' pointer changes every time you create a new island. node = create(name); if (start == NULL) { start = node; } if (i != NULL) { i->next = node; } } display(start); release(start); return 0; }
建立3個island指針,start表明該鏈表(航線)的起始位置,i做爲迭代器將多個節點串聯起來,node是新建立的island,每次建立都會更新node的地址,鏈表中每一個節點只是一段內存(連續或不連續),並無實際的名稱。
邏輯步驟:接收一個island名,建立island,用node指針標記這一新建節點,若是當前start爲空,將start賦值爲node,若是i不爲空,將i->next指向node,最後i=node,將i指向新建立的節點(爲鏈接下一個節點作準備),循環這一步驟。完成這一系列操做後,node,i,i->next彷佛都指向同一塊內存。
單鏈表的建立在邏輯上絕對不會有太大出入,一個遞歸結構做爲節點,循環建立節點,用一個臨時指針串聯全部節點,只start起始指針標記這一鏈表。
代碼已上傳到github:https://github.com/AlexTuan1024/egsonhfc.git