【文章內(nèi)容簡介】
例 86 結(jié)構(gòu)體指針作函數(shù)參數(shù)示例。 結(jié)構(gòu)體數(shù)組名 鏈表概述 ? 使用鏈表存儲學(xué)生信息 ? 鏈表的特點 ? 動態(tài)內(nèi)存管理函數(shù) ? 定義鏈表結(jié)構(gòu) 鏈表的概念 ? 鏈表 是結(jié)構(gòu)體最重要的應(yīng)用,它 是一種非固定長度的數(shù)據(jù)結(jié)構(gòu) , 是一種動態(tài)存儲技術(shù) ,它能夠根據(jù)數(shù)據(jù)的結(jié)構(gòu)特點和數(shù)量使用內(nèi)存,尤其適用于數(shù)據(jù)個數(shù)可變的數(shù)據(jù)存儲。 ? 使用鏈表存儲表中前 3個學(xué)生數(shù)據(jù)。 9 9 0 1l i u j i aM8 79 9 0 2w a n g k a iM8 99 9 0 3x i a o h u aF8 1N U L Lh e a d學(xué)號 姓名 性別 成績 9901 liujia M 87 9902 wangkai M 89 9903 xiaohua F 81 9904 zhangli F 82 9905 wangfeng M 88 ⑴ 用 calloc()申請一段內(nèi)存 M,并把它分成兩部分:一部分存儲數(shù)據(jù);另一部分存儲下一個內(nèi)存段的地址。 ⑵ 將一個學(xué)生數(shù)據(jù)存儲在 M的數(shù)據(jù)區(qū)中。 ⑶ 若當(dāng)前是第一個數(shù)據(jù),則將 M的首地址保存在指針變量 head中;否則將 M的首地 保存在上一個內(nèi)存段中。 ⑷ 重復(fù)⑴、⑵、⑶的過程,直到所有數(shù)據(jù)存儲完畢,在最后一段內(nèi)存的地址區(qū)存儲結(jié)束標(biāo)志。 鏈表的特點 ⑴ 鏈表中的結(jié)點具有完全相同的結(jié)構(gòu),每一個結(jié)點存儲一個獨立的結(jié)構(gòu)體數(shù)據(jù); ⑵ 鏈表的結(jié)點由系統(tǒng)隨機分配,它們在內(nèi)存中的位置可能是相鄰的,也可能是不相鄰的,結(jié)點之間的聯(lián)系是通過指針域?qū)崿F(xiàn)的; ⑶ 為了能準(zhǔn)確的定位第一個結(jié)點,每個鏈表要有一個表頭指針,從第一個結(jié)點開始,沿指針鏈能遍歷鏈表中的所有結(jié)點; ⑷ 鏈表中的結(jié)點是在需要時用 calloc()申請的,當(dāng)不再需要時,應(yīng)有 free()函數(shù)釋放所占用的內(nèi)存段。 ⑸ 一個鏈表不需要事先說明它要包括的結(jié)點數(shù)目,在需要存儲新的數(shù)據(jù)時,就可增加結(jié)點,需要刪除數(shù)據(jù)時,就減少結(jié)點,鏈表結(jié)點是動態(tài)變化的。 動態(tài)內(nèi)存管理函數(shù) ?動態(tài)分配內(nèi)存 按需分配內(nèi)存,申請獲得制。 ?C語言通過動態(tài)內(nèi)存管理函數(shù),實現(xiàn)動態(tài)內(nèi)存管理。鏈表每一個結(jié)點的建立和刪除過程,都需要使用動態(tài)內(nèi)存管理函數(shù)。 動態(tài)內(nèi)存管理函數(shù) 1. malloc()函數(shù) ?函數(shù)原型 void *malloc(unsigned int size)。 ?功能 分配一塊長度為 size字節(jié)的連續(xù)空間,并將該空間的首地址作為函數(shù)的返回值。如果函數(shù)沒有成功執(zhí)行,返回值為空指針( NULL或 0)。由于返回的指針的基類型為 void,應(yīng)該通過顯式類型轉(zhuǎn)換后才能存入其他基類型的指針變量中,否則會有警告提示。 例如: int *p。 p=(int *)malloc(sizeof(int))。 動態(tài)內(nèi)存管理函數(shù) 2. free()函數(shù) ?函數(shù)原型 void free(void *block)。 ?功能 釋放以前分配給指針變量 block的動態(tài)空間,但指針變量 block不會自動變成空指針。 3. calloc()函數(shù) ?函數(shù)原型 void *calloc(unsigned n,unsigned size)。 ?功能 以 size為單位大小共分配 n*size個字節(jié)的連續(xù)空間,并將該空間的首地址作為函數(shù)的返回值。如果函數(shù)沒有成功執(zhí)行,返回值為空指針(NULL或 0)。 例如: int *p。 p=(int *)calloc(10,sizeof(int))。 定義鏈表結(jié)構(gòu) ? 要定義一個鏈表結(jié)點的結(jié)構(gòu),須有兩項內(nèi)容: ? 定義數(shù)據(jù)存儲所對應(yīng)的各個成員; ? 定義指向其他結(jié)點的指針成員。 例如: 假若要用鏈表逐個存儲一批整數(shù),其結(jié)點結(jié)構(gòu)可定義如下: struct node { int data。 struct node *next。 }。 n e w d a ta n e x t存儲具體數(shù)據(jù) 存儲下一個節(jié)點的地址 d a t a 1 d a t a 2 d a t a 3 d a t a n ∧. . .h e a d?struct node類型的結(jié)點形成的鏈表 頭指針 空指針 定義鏈表結(jié)構(gòu) 9 9 0 1l i u j i aM8 79 9 0 2w a n g k a iM8 99 9 0 3x i a o h u aF8 1N U L Lh e a d學(xué)號 姓名 性別 成績 9901 liujia M 87 9902 wangkai M 89 9903 xiaohua F 81 9904 zhangli F 82 9905 wangfeng M 88 struct student { int num。 char name[20]。 char sex。 int score。 struct student *next。 }。 必須的成員,否則構(gòu)不成鏈表 ?學(xué)生鏈表的結(jié)點定義 ?結(jié)點 鏈表的基本操作 ? 鏈表結(jié)點的插入 ? 鏈表結(jié)點的刪除 ? 鏈表結(jié)點的查找 鏈表結(jié)點的插入 ? 在鏈表中插入結(jié)點,就是把一個新結(jié)點連接到鏈表中。 ? 兩種情況: ?在空鏈表中插入一個結(jié)點; ?在鏈表的 p結(jié)點之后插入一個新結(jié)點。 鏈表結(jié)點的插入 1.在空鏈表中插入一個結(jié)點 空鏈表就是頭指針 head為空的鏈表。 ⑴ 申請一個 new結(jié)點。 new=(struct node *)calloc(1,sizeof(struct node))。 ⑵ 為 p結(jié)點填充數(shù)據(jù)。 將要存儲的數(shù)據(jù)對應(yīng)賦值給 p結(jié)點數(shù)據(jù)域的各個成員。 ⑶ 修改有關(guān)指針的指向。 ① 將 new的 next成員置空,使 new結(jié)點成為鏈表的最后一個結(jié)點。 ② 將 head指向 new結(jié)點。 n e w d a ta n e x th e a d d a t a∧ 鏈表結(jié)點的插入 2.在 head鏈表的 p結(jié)點之后插入一個結(jié)點 head鏈表和要插入結(jié)點 new如圖所示。要將 new結(jié)點插入在 p結(jié)點之后,就是將 new結(jié)點變成結(jié)點 C的下一個結(jié)點,而使 new的下一個結(jié)點成為結(jié)點 D。 ⑴ 使 new的指針域存儲結(jié)點 D的首地址。 newnext=pnext。 ⑵ 把 new的首地址存儲到結(jié)點 p的指針域中 。 pnext=new。 d a t a 1 d a t a 2 d a t a 3 d a t a 4 ∧h e a dpd a t