1.3链表
鏈表的物理存儲(chǔ)結(jié)構(gòu)是用一組地址任意的存儲(chǔ)單元存儲(chǔ)數(shù)據(jù)的。不像順序表占據(jù)連續(xù)的一段內(nèi)存空間,而是將存儲(chǔ)單元分散在內(nèi)存的任意地址上。
?
鏈表結(jié)構(gòu)中,每個(gè)數(shù)據(jù)元素記錄都存放到鏈表的一個(gè)節(jié)點(diǎn)(node)中,而每個(gè)節(jié)點(diǎn)之間由指針將其連接在一起,形成了”鏈“的結(jié)構(gòu)、
鏈表每個(gè)節(jié)點(diǎn)中,都必須有一個(gè)專門用來存放指針(地址)的域,用這個(gè)指針域來存放后繼結(jié)點(diǎn)的地址,這樣就達(dá)成了連接后繼結(jié)點(diǎn)的目的。
一條鏈表通常有1個(gè)”表頭“,是一個(gè)指針變量,用來存放第一個(gè)節(jié)點(diǎn)地址。此外,一條鏈表的最后一個(gè)節(jié)點(diǎn)的指針域要置空(NULL),表示該節(jié)點(diǎn)為鏈表的尾節(jié)點(diǎn),因?yàn)樗疀]有后繼結(jié)點(diǎn)了。
?
鏈表特征:
1)每個(gè)節(jié)點(diǎn)包括兩部分:數(shù)據(jù)域和指針域。其中數(shù)據(jù)域用來存放數(shù)據(jù)元素本身的信息,指針域用來存放后繼結(jié)點(diǎn)的地址。
2)鏈表邏輯上是連續(xù)的,而物理上不一定連續(xù)存儲(chǔ)節(jié)點(diǎn)、
3)只要獲得鏈表的頭節(jié)點(diǎn),就可以通過指針遍歷整條鏈表。
?
實(shí)例:編寫一個(gè)程序,要求:從終端輸入一組整數(shù)(大于10個(gè)數(shù)),以0作為結(jié)束標(biāo)志,將這一組整數(shù)存放在一個(gè)鏈表中,(結(jié)束標(biāo)志0不包括在內(nèi)),打印出該鏈表中的值。然后刪除該鏈表中的第五個(gè)元素,打印出刪除后的結(jié)果。最后在內(nèi)存中釋放掉該鏈表。
?
#include"stdio.h" #include"stdlib.h" typedef int ElemType;typedef struct node{ElemType data;struct node *next; }LNode,*LinkList;LinkList GreatLinkList(int n) { //創(chuàng)建一個(gè)長(zhǎng)度為n的鏈表 LinkList p,r,list=NULL;ElemType e;int i;for(i=1;i<=n;i++) {scanf("%d",&e); //輸入結(jié)點(diǎn)的內(nèi)容 p=(LinkList)malloc(sizeof(LNode));//為新建的結(jié)點(diǎn)開辟內(nèi)存空間 p->data=e; //元素賦值 p->next=NULL;if(!list)list=p; //賦值鏈表頭指針 elser->next=p; //將結(jié)點(diǎn)連入鏈表 r=p;}return list; //返回鏈表頭指針 }void insertList(LinkList *list,LinkList q,ElemType e) {//向鏈表中插入結(jié)點(diǎn) e LinkList p;p=(LinkList)malloc(sizeof(LNode));//為新建的結(jié)點(diǎn)開辟新的內(nèi)存空間 ,生成一個(gè)新結(jié)點(diǎn),由p指向它 p->data=e; //向該結(jié)點(diǎn)的數(shù)據(jù)域賦值e if(!*list) {*list=p; //list內(nèi)容為NULL時(shí),表示該鏈表為空,賦值鏈表頭指針 p->next=NULL;} //當(dāng)鏈表為空時(shí)q沒有意義,只能在頭結(jié)點(diǎn)后面插入第一個(gè)元素 else {p->next=q->next;//當(dāng)鏈表不為空時(shí),認(rèn)為q指向的結(jié)點(diǎn)一定存在,將q指向的結(jié)點(diǎn)的next域的值賦給p指向結(jié)點(diǎn)的next域q->next=p; } }void delLink(LinkList *list,LinkList q) { //刪除鏈表的某結(jié)點(diǎn) LinkList r;if(q==*list) { //如果刪除第一個(gè)結(jié)點(diǎn) *list=q->next;free(q);}else { //刪除其他結(jié)點(diǎn) for(r=*list;r->next!=q;r=r->next)if(r->next!=NULL) {r->next=q->next;free(q);}} }void destroyLinkList(LinkList *list) { //銷毀一個(gè)鏈表 LinkList p,q;p=*list;while(p) { //循環(huán)釋放掉每一個(gè)鏈表結(jié)點(diǎn) q=p->next;free(p);p=q;}*list=NULL;//將*list的內(nèi)容置為NULL,這樣主函數(shù)中的鏈表list就為空,防止了list變?yōu)橐爸羔?#xff0c;而且鏈表在內(nèi)存中也完全被釋放掉了。 }int main() {int e,i;LinkList l,q;q=l=GreatLinkList(l);//創(chuàng)建一個(gè)鏈表結(jié)點(diǎn),q和l都指向該結(jié)點(diǎn) scanf("%d",&e);while(e) { //循環(huán)輸入數(shù)據(jù),同時(shí)插入新生成的結(jié)點(diǎn) insertList(&l,q,e);q=q->next;scanf("%d",&e);}q=l;printf("the content of the linklist\n");while(q) { //輸出鏈表中的內(nèi)容 printf("%d",q->data);q=q->next;}q=l;printf("\nDelete the fifth element");for(i=0;i<4;i++) { //將指針q指向鏈表的第五個(gè)元素 if(q==NULL) { //確保此時(shí)鏈表的長(zhǎng)度大于等于5,否則將是非法操作 printf("the length of the linklist is smaller than 5!");}q=q->next;}delLink(&l,q); //找到鏈表中第五個(gè)元素,用q指向它,再刪除q所指的結(jié)點(diǎn) q=l;while(q) { //打印出刪除后的結(jié)果 printf("%d",q->data);q=q->next;}destroyLinkList(&l); //銷毀該鏈表 return 0; }
創(chuàng)建鏈表注意:
(1)用malloc()函數(shù)在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)(堆內(nèi)存)中開辟一塊大小為sizeof(LNode)的空間,并將其地址賦給LinkList類型變量p,(LinkList為指向LNode變量的類型,LNode為前面定義的鏈表結(jié)點(diǎn)類型)。然后將數(shù)據(jù)e存入該結(jié)點(diǎn)的數(shù)據(jù)域data,指針域存放NULL。
(2)若指針變量list為空,說明本次生存的結(jié)點(diǎn)是第一個(gè)結(jié)點(diǎn)……
(3)若指針變量list不為空,說明本次生存的結(jié)點(diǎn)不是第一個(gè)結(jié)點(diǎn),將p賦給r->next。此處的r是一個(gè)LinkList類型變量,永遠(yuǎn)指向原先鏈表的最后一個(gè)結(jié)點(diǎn),也就是要插入結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)。
(4)再將p賦值給r,目的是使r再次指向最后的結(jié)點(diǎn),以便生成鏈表的下一個(gè)結(jié)點(diǎn),即保證r永遠(yuǎn)指向原先鏈表的最后一個(gè)結(jié)點(diǎn)。
(5)重復(fù)(1)~(4)n次,生成n個(gè)結(jié)點(diǎn)的鏈表
(6)最后生成的鏈表的頭指針list返回主調(diào)函數(shù),通過list就可以訪問到該鏈表的每一個(gè)結(jié)點(diǎn)。
?
刪除鏈表注意:
從非空鏈表刪除q所指的結(jié)點(diǎn),考慮3種情況:
(1)q所指向的是鏈表的第一個(gè)結(jié)點(diǎn)
(2)q所指向的結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)的指針已知
(3)q所指向的結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)的指針未知
?
銷毀鏈表注意
鏈表使用完建議銷毀,因?yàn)殒湵肀旧頃?huì)占用內(nèi)存空間。若一個(gè)系統(tǒng)中使用很多鏈表,而使用完又不及時(shí)銷毀,那么這些垃圾空間積累過多,最終導(dǎo)致內(nèi)存的泄露甚至程序的崩潰。
?
————————————————————————
————————————————————————
程序運(yùn)行時(shí)候,刪除第5個(gè)元素,沒有顯示出預(yù)期結(jié)果。運(yùn)行環(huán)境在DEV。
轉(zhuǎn)載于:https://www.cnblogs.com/dd2hm/p/6838694.html
總結(jié)
- 上一篇: java获取mp3的时长和播放mp3文件
- 下一篇: iscroll5制作上下拉刷新 tab出