Head First C學習日誌 第六章用堆進行動態存儲

書中的例子是,在多座島嶼間規劃航線,並記錄,將島嶼做爲節點,數據結構以下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

相關文章
相關標籤/搜索