




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第7章結(jié)構(gòu)體
7.1結(jié)構(gòu)體類型與結(jié)構(gòu)體變量
在實(shí)際編程中除了常常要處理相同類型的數(shù)據(jù)外,還經(jīng)常要處理不同類型的相關(guān)數(shù)據(jù)。例如,一個(gè)學(xué)生的信息可能包括學(xué)號(hào)、姓名、性別和考試成績(jī)四項(xiàng)信息。學(xué)號(hào)可定義為整型,姓名可定義為字符串類型,性別可定義為字符型,考試成績(jī)可定義為實(shí)型數(shù)組。這些數(shù)據(jù)雖然類型不同,但是它們是相關(guān)的,共同表示某個(gè)學(xué)生的信息。顯然,這些數(shù)據(jù)既不適合用基本類型處理也不適合用數(shù)組處理,這種數(shù)據(jù)需要用可包含不同類型成員的構(gòu)造類型處理,為此,C語言提供了滿足這種需求的數(shù)據(jù)類型——結(jié)構(gòu)體類型。7.1.1結(jié)構(gòu)體類型的定義
結(jié)構(gòu)體類型中可以包含若干相同或不同類型的成員,這些成員代表相關(guān)的信息。例如,日期結(jié)構(gòu)體類型可定義為:structdate{intyear;intmonth;intday;};學(xué)生結(jié)構(gòu)體類型可如下定義:structstudent{intnumber;/*學(xué)號(hào)*/charname[8];/*姓名*/charsex;/*性別*/floatscore[4];/*成績(jī)*/};定義的格式為:struct結(jié)構(gòu)體名{類型名成員名1;類型名成員名2;
……
類型名成員名n;
};說明:①struct是結(jié)構(gòu)體類型的標(biāo)識(shí),是關(guān)鍵字。struct和后面的結(jié)構(gòu)體名共同構(gòu)成結(jié)構(gòu)體類型名。結(jié)構(gòu)體名應(yīng)符合標(biāo)識(shí)符的命名規(guī)則。②結(jié)構(gòu)體所有成員的定義用花括弧括起來。結(jié)構(gòu)體成員的定義方式和變量的定義方式一樣,成員類型可以是基本類型的,也可以是構(gòu)造類型的。各成員之間用分號(hào)分隔。③結(jié)構(gòu)體內(nèi)的各個(gè)成員名不能重名,但可以與結(jié)構(gòu)體外其他標(biāo)識(shí)符同名。7.1.2結(jié)構(gòu)體變量的定義結(jié)構(gòu)體變量的定義可用三種方式:①用已經(jīng)定義的結(jié)構(gòu)體類型定義結(jié)構(gòu)體變量。例如,用前面已經(jīng)定義的structstudent定義變量stu:
structstudentstu;②定義結(jié)構(gòu)體類型的同時(shí)定義結(jié)構(gòu)體變量。例如,定義結(jié)構(gòu)類型structstudent的同時(shí)定義變量stu1,stu2:structstudent{intnumber;/*學(xué)號(hào)*/charname[8];/*姓名*/charsex;/*性別*/floatscore[4];/*成績(jī)*/}stu1,stu2;③定義無名結(jié)構(gòu)體類型的同時(shí)定義結(jié)構(gòu)體變量。因?yàn)檫@種定義形式省略了結(jié)構(gòu)體名,只有不再需要定義此種類型變量的情況才可采用這種方式。例如,定義變量stu:struct{intnumber;/*學(xué)號(hào)*/charname[8];/*姓名*/charsex;/*性別*/floatscore[4];/*成績(jī)*/}stu;結(jié)構(gòu)體變量各個(gè)成員按照定義的順序依次占用連續(xù)的空間。需要注意,結(jié)構(gòu)體人員也可以是結(jié)構(gòu)體變量,如:structdate{intmonth;intday;intyear;};struct{longintnum;charname[20];charsex;intage;
structdate
birthday;floatscore;charaddr[20];}student1,student2;7.1.3結(jié)構(gòu)體變量的指針可以定義指針變量指向結(jié)構(gòu)體類型變量。例如,語句 structstudent*p=&stu;定義了指向結(jié)構(gòu)體的指針變量p,并且使其指向結(jié)構(gòu)體變量stu。stu的存儲(chǔ)結(jié)構(gòu)和p指針的示意圖如圖7.1所示。圖7.1結(jié)構(gòu)體變量的存儲(chǔ)結(jié)構(gòu)及其指針例如,定義變量stu并初始化。如:structstudent{longintnum;charname[20];charsex;charaddr[20];}stu={89031,“l(fā)ilin”,’M’,“123BeijingRoad”};7.1.4結(jié)構(gòu)體變量的初始化結(jié)構(gòu)體變量同樣既可以在定義之后初始化,也可以在定義的同時(shí)進(jìn)行初始化。若在定義之后進(jìn)行初始化操作,只能對(duì)每個(gè)成員單獨(dú)進(jìn)行賦值。若在定義變量的同時(shí)進(jìn)行初始化,則用一對(duì)花括弧括起各個(gè)成員值的列表并用賦值號(hào)和變量連接,成員值之間逗號(hào)分隔,具體格式為:
結(jié)構(gòu)體類型名結(jié)構(gòu)體變量={成員值列表};7.1.5結(jié)構(gòu)體變量的引用對(duì)于結(jié)構(gòu)體變量,只能引用結(jié)構(gòu)體變量的成員,不能引用整個(gè)結(jié)構(gòu)體變量。引用結(jié)構(gòu)體變量成員的形式為:(1)通過結(jié)構(gòu)體變量名引用:
結(jié)構(gòu)體變量名.成員名其中“.”稱為成員運(yùn)算符。(2)通過指向結(jié)構(gòu)體變量的指針引用:
(*指針變量名).成員名或指針變量名
成員名這兩種表示形式完全等價(jià)。例如,語句“structstudent*p=&stu;”之后,變量stu的成員sex有以下三種引用形式:①stu.sex②(*p).sex③p
sex注意:如果結(jié)構(gòu)體的成員仍然是構(gòu)造類型,則需要逐級(jí)引用,直至最低級(jí)的成員,即只能對(duì)結(jié)構(gòu)體變量最低級(jí)的成員進(jìn)行存取和運(yùn)算。例如,變量stu的成員score必須引用其最低級(jí)成員,如stu.score[0](*p).score[2]p
score[1]。結(jié)構(gòu)體成員的運(yùn)算規(guī)則與同類型的變量的運(yùn)算規(guī)則相同。【例7.1】輸入學(xué)生的各項(xiàng)信息,計(jì)算總分和平均成績(jī)后輸出。#include"stdio.h"structdate{intyear;intmonth;intday;};/*定義結(jié)構(gòu)體類型structdate*/structstudent{intnumber;/*學(xué)號(hào)*/charname[10];/*姓名*/structdatebirthday;/*生日,structdate類型*/floatscore[4];/*四門課成績(jī)*/floattotal;/*總分*/floatave;/*平均成績(jī)*/};/*定義結(jié)構(gòu)體類型structstudent*/main(){structstudentstu,*p;intk;printf("pleaseenternumber&name:");scanf("%d%s",&stu.number,);printf("pleaseenterbirthday(year,month,day):");scanf("%d%d%d",&stu.birthday.year,&stu.birthday.month, &stu.birthday.day);printf("pleaseenterthescore(4):");for(stu.total=0,k=0;k<4;k++){scanf("%f",&stu.score[k]);stu.total+=stu.score[k];}/*計(jì)算總成績(jī)*/stu.ave=stu.total/4;/*計(jì)算平均成績(jī)*/p=&stu;printf("number:%d\n",p
number);printf("name:%s\n",p
name);printf("birthday:%d,%d,%d\n",(*p).birthday.year,(*p).birthday.month, (*p).birthday.day);printf("score:");for(k=0;k<4;k++)printf("%6.2f",p
score[k]);printf("\ntotal:%6.2f\n",stu.total);printf("average:%6.2f\n",stu.ave);}7.2結(jié)構(gòu)體數(shù)組7.2.1結(jié)構(gòu)體數(shù)組的定義和初始化若數(shù)組元素的類型為結(jié)構(gòu)體類型,則稱該數(shù)組為結(jié)構(gòu)體數(shù)組。定義結(jié)構(gòu)體數(shù)組的同時(shí)也可對(duì)數(shù)組進(jìn)行初始化,例如,structstudent{intnumber;/*學(xué)號(hào)*/charname[10];/*姓名*/floatscore[4];/*四門課程成績(jī)*/floattotal;/*總分*/floatave;/*平均成績(jī)*/}stu[3]={{461,"Liu",{80,78,67,80},0,0},{032,"Lin",{98,78,86,90},0,0},{103,"Chen",{79,89,68,80},0,0}};結(jié)構(gòu)體數(shù)組stu的邏輯示意圖如圖7.2。7.2.2結(jié)構(gòu)體數(shù)組的引用
結(jié)構(gòu)體數(shù)組元素也是通過數(shù)組名和下標(biāo)來引用,但要注意只能對(duì)最低級(jí)的成員進(jìn)行存取和運(yùn)算。引用的一般形式為:數(shù)組名[下標(biāo)].成員名例如,stu[1].number、stu[0].score[2]、stu[2].ave等合法。
通過指針引用結(jié)構(gòu)體數(shù)組元素的形式和通過指針引用結(jié)構(gòu)變量形式一樣,為:(*指針變量名).成員名或指針變量名
成員名例如,語句“p=&stu[1];”之后,(*p).number(第1個(gè)學(xué)生的學(xué)號(hào))(p-1)
score[2](第0個(gè)學(xué)生的第2門課的成績(jī))p
ave;(第1個(gè)學(xué)生的平均成績(jī))是合法的引用形式。【例7.2】計(jì)算某班期末考試中所有學(xué)生的總分和平均成績(jī)。#defineN5#include"stdio.h"structstudent{intnumber;/*學(xué)號(hào)*/charname[10];/*姓名*/intscore[4];/*四門課程成績(jī)*/inttotal;/*總分*/floatave;/*平均成績(jī)*/};main(){structstudentstu[N],*p;inti,k;for(i=0,p=stu;p<stu
+N;p++,i++)/*輸入學(xué)生的信息*/{printf("the%dstudent\n",i);printf("number&name:");scanf("%d%s",&p->number,p->name);printf("score(4):");for(p->total=0,k=0;k<4;k++){scanf("%d",&p->score[k]);p->total+=p->score[k];/*計(jì)算總成績(jī)*/}p->ave=p->total/4;/*計(jì)算平均成績(jī)*/}for(i=0;i<N;i++)/*輸出*/{printf("number:%6d\n",stu[i].number);printf("name:%s\n",stu[i].name);printf("score:");for(k=0;k<4;k++)printf("%4d",stu[i].score[k]);printf("\ntotal=%4daverage=%10.2f\n",stu[i].total,stu[i].ave);}}7.3結(jié)構(gòu)體和函數(shù)7.3.1結(jié)構(gòu)體指針變量作為函數(shù)參數(shù)
C語言允許函數(shù)之間傳遞結(jié)構(gòu)體變量,但是形參結(jié)構(gòu)體變量占用內(nèi)存空間、接收實(shí)參數(shù)據(jù)帶來空間和時(shí)間的巨大開銷。因此語法上雖然允許,但一般很少采用這種方式,而采用結(jié)構(gòu)體指針作為函數(shù)參數(shù)。參數(shù)傳遞時(shí)只需傳遞一個(gè)地址,空間和時(shí)間的代價(jià)都很小。而且,可以通過指針對(duì)實(shí)參結(jié)構(gòu)體變量的空間操作,從而改變實(shí)參的值?!纠?.3】重新編寫例7.2。#defineN3#include"stdio.h"structstudent{intnumber;/*學(xué)號(hào)*/charname[10];/*姓名*/floatscore[4];/*四門課程成績(jī)*/floattotal;/*總分*/floatave;/*平均成績(jī)*/};voidinput(structstudent*stu)/*輸入學(xué)生信息*/{intk;printf("number&name:");scanf("%d%s",&stu->number,stu->name);printf("score(4):");for(k=0;k<4;k++)scanf("%f",&stu->score[k]);}
voidtotal_average(structstudent*stu)/*計(jì)算總成績(jī)和平均值*/{intk;stu->total=0;for(k=0;k<4;k++)stu->total+=stu->score[k];stu->ave=stu->total/4;}voidoutput(structstudent*stu)/*輸出學(xué)生信息*/{intk;printf("number:%6d\n",stu->number);printf("name:%s\n",stu->name);printf("score:");for(k=0;k<4;k++)printf("%6.2f",stu->score[k]);printf("\ntotal=%10.2faverage=%10.2f\n",stu->total,stu->ave);}main(){structstudentstu[N],*p;inti;for(i=0;i<N;i++)/*輸入學(xué)生的信息*/{printf("the%dstudent\n",i);input(&stu[i]);total_average(&stu[i]);/*計(jì)算平均成績(jī)*/}printf("\n");for(i=0;i<N;i++)output(&stu[i]);/*輸出*/}例7.3中各個(gè)函數(shù)的參數(shù)都是基類型為structstudent的指針類型,實(shí)參是結(jié)構(gòu)體變量stu[j]的地址。發(fā)生函數(shù)調(diào)用時(shí),將結(jié)構(gòu)體變量的地址賦值給形參指針stu,這樣形參指針就指向了結(jié)構(gòu)體變量stu[j]。因此在input、total_average函數(shù)中對(duì)結(jié)構(gòu)體變量的操作結(jié)果都在實(shí)參指向的結(jié)構(gòu)體變量上得到體現(xiàn)。7.3.2結(jié)構(gòu)體數(shù)組作函數(shù)參數(shù)向函數(shù)傳遞結(jié)構(gòu)體數(shù)組與傳遞其它數(shù)組一樣,實(shí)質(zhì)上也是傳遞數(shù)組的首地址。形參數(shù)組與實(shí)參數(shù)組使用共同的內(nèi)存單元。形參、實(shí)參是同類型的結(jié)構(gòu)體數(shù)組名或結(jié)構(gòu)體指針?!纠?.4】重新編寫例7.2。#defineN5#include"stdio.h"structstudent{intnumber;/*學(xué)號(hào)*/charname[10];/*姓名*/floatscore[4];/*四門課程成績(jī)*/floattotal;/*總分*/floatave;/*平均成績(jī)*/};voidinput(structstudentstu[],intn)/*輸入學(xué)生的信息*/{inti,k;for(i=0;i<n;i++){printf("the%dstudent\n",i);printf("number&name:");scanf("%d%s",&stu[i].number,stu[i].name);printf("score(4):");for(k=0;k<4;k++)scanf("%f",&stu[i].score[k]);}}voidtotal_average(structstudent*stu,intn)/*計(jì)算總成績(jī)和平均值*/{intk;structstudent*p;p=stu+n;for(;stu<p;stu++){stu->total=0;for(k=0;k<4;k++)stu->total+=stu->score[k];stu->ave=stu->total/4;}}voidoutput(structstudent*stu,intn)/*輸出處理后的學(xué)生信息*/{intk,i;for(i=0;i<n;i++){printf("number:%6d\n",(stu+i)->number);printf("name:%s\n",(stu+i)->name);printf("score:");for(k=0;k<4;k++)printf("%6.2f",(stu+i)->score[k]);printf("\ntotal=%10.2faverage=%10.2f\n",(stu+i)->total,(stu+i)->ave);}}main(){structstudentstu[N];structstudent*q=stu;
floatarg,*point2=&arg;
/*告訴TC需要做浮點(diǎn)數(shù)輸入轉(zhuǎn) 換,以便TC就會(huì)把浮點(diǎn)轉(zhuǎn)換格式安裝 到可執(zhí)行程序里*/input(q,N);total_average(stu,N);output(stu,N);}7.4鏈表鏈表是一種常見的重要的數(shù)據(jù)結(jié)構(gòu),可以根據(jù)需要?jiǎng)討B(tài)地分配存儲(chǔ)單元,因此不會(huì)浪費(fèi)內(nèi)存空間?!耦^指針(head)變量的地址指向鏈表的第一個(gè)元素(稱 為“結(jié)點(diǎn)”)?!窠Y(jié)點(diǎn)兩個(gè)部分:一為用戶的實(shí)際數(shù)據(jù),二為下一個(gè)結(jié)點(diǎn)的 地址。●最后一個(gè)結(jié)點(diǎn)稱為“表尾”,地址存放“NULL”,表示 地址 為空,即不再指向任何結(jié)點(diǎn),因此鏈表到此結(jié)束?!矜湵淼母鱾€(gè)結(jié)點(diǎn)在內(nèi)存中可以不是連續(xù)存放的。利用結(jié)構(gòu)體變量來表示結(jié)點(diǎn)是最合適不過的。對(duì)于上圖的鏈表結(jié)點(diǎn),顯然可以用以下結(jié)構(gòu)體表示:
structstudent {intnum; floatscore; structstudent*next;};7.4.1靜態(tài)鏈表的建立與輸出【例7.5】建立圖7.3所示的簡(jiǎn)單鏈表,并輸出各結(jié)點(diǎn)中的數(shù)據(jù)。#defineNULL0#include<stdio.h>structstudent /*定義結(jié)點(diǎn)的結(jié)構(gòu)體類型*/{longnum;/*學(xué)號(hào)一般很長(zhǎng),“數(shù)值”很大,所以用 長(zhǎng)整形表示*/floatscore;structstudent*next;};main(){structstudenta,b,c,*head,*p;a.num=80101;a.score=91.5;/*對(duì)結(jié)點(diǎn)的num和score成員賦值*/b.num=80103;b.score=89.5;c.num=80107;c.score=76;head=&a;/*將結(jié)點(diǎn)a的起始地址賦給頭指針,使頭指針指向結(jié)點(diǎn)a*/a.next=&b; /*將結(jié)點(diǎn)b的起始地址賦給a結(jié)點(diǎn)的next成員*/b.next=&c; /*將結(jié)點(diǎn)c的起始地址賦給b結(jié)點(diǎn)的next成員*/ c.next=NULL; /*c結(jié)點(diǎn)的next成員存放空地址,c結(jié)點(diǎn)為表尾*/p=head;/*使p指針指向結(jié)點(diǎn)a*/do{printf(“%ld%5.1f\n”,p->num,p->score);/*輸出p指向的結(jié)點(diǎn)的數(shù)據(jù)*/p=p->next; /*使p指向下一結(jié)點(diǎn)*/}while(p!=NULL); /*當(dāng)p指針的值非空時(shí)繼續(xù)循環(huán)*/}程序運(yùn)行結(jié)果為:本程序中,所有結(jié)點(diǎn)都是在程序中定義的,不是動(dòng)態(tài)申請(qǐng)空間建立的,不能用完后自動(dòng)釋放,這種鏈表稱為靜態(tài)鏈表。
7.4.2處理動(dòng)態(tài)鏈表需要的函數(shù)動(dòng)態(tài)鏈表的結(jié)點(diǎn)是動(dòng)態(tài)分配的,即在需要的時(shí)候才開辟某個(gè)結(jié)點(diǎn)的存儲(chǔ)單元。為了動(dòng)態(tài)地開辟和釋放存儲(chǔ)單元,C語言編譯系統(tǒng)提供了以下函數(shù)。1.malloc函數(shù)函數(shù)原形:void*malloc(unsignedintsize);
作用:在內(nèi)存的動(dòng)態(tài)存區(qū)分配一個(gè)長(zhǎng)度為size個(gè)字節(jié)的連續(xù)存區(qū),函數(shù)的返回值是一個(gè)指向該存區(qū)首址的指針(其類型為void型)。如果由于內(nèi)存不足等原因使該函數(shù)未能成功執(zhí)行,則返回空指針NULL。
2.calloc函數(shù)函數(shù)原形:void*calloc(unsignedn,unsignedsize);作用:在內(nèi)存的動(dòng)態(tài)存區(qū)在分配n個(gè)長(zhǎng)度為size個(gè)字節(jié)的連續(xù)存區(qū),函數(shù)的返回值是一個(gè)指向該存區(qū)首址的指針(其類型為void型)。如果由于內(nèi)存不足等原因使該函數(shù)未能成功執(zhí)行,則返回空指針NULL。使用calloc函數(shù)能夠?yàn)橐痪S數(shù)組開辟動(dòng)態(tài)存儲(chǔ)空間,n為數(shù)組元素的個(gè)數(shù),每個(gè)元素的長(zhǎng)度為size個(gè)字節(jié)。free函數(shù)函數(shù)原形:voidfree(void*p);
作用:釋放p指向的內(nèi)存區(qū),使這部分內(nèi)存區(qū)域能夠 被其它變量使用,p為最近一次malloc/calloc的 返回值,即最近一次分配的空間。free函數(shù)沒有返 回值。7.4.3建立動(dòng)態(tài)鏈表所謂建立動(dòng)態(tài)鏈表是指在程序執(zhí)行過程中逐個(gè)建立鏈表的各個(gè)結(jié)點(diǎn),即●逐個(gè)開辟結(jié)點(diǎn)的內(nèi)存空間●再輸入該結(jié)點(diǎn)的數(shù)據(jù)●然后建立起前后結(jié)點(diǎn)之間的相連關(guān)系。【例7.6】用建立單向動(dòng)態(tài)鏈表的方法建立圖7.3所示的鏈表。 為了建立一個(gè)單向動(dòng)態(tài)鏈表,需要設(shè)置3個(gè)指針變量head、p1和p2,它們都指向structstudent類型數(shù)據(jù)。P1指向新開的結(jié)點(diǎn),P2指向鏈表中最后一個(gè)結(jié)點(diǎn),先使head的值為NULL,即不指向任何結(jié)點(diǎn),鏈表為空。
圖7.4建立第一個(gè)結(jié)點(diǎn)●先用malloc函數(shù)開辟第一個(gè)結(jié)點(diǎn),即在內(nèi)存的動(dòng)態(tài)存區(qū)分配一個(gè)一定長(zhǎng)度的連續(xù)存區(qū),并且使p1指向它。●由于當(dāng)前鏈表為空,所以p2也指向剛分配的連續(xù)存區(qū)。●當(dāng)輸入的學(xué)號(hào)不為0時(shí),就開始為這個(gè)學(xué)生建立結(jié)點(diǎn)。●從鍵盤上讀入第一個(gè)學(xué)生的數(shù)據(jù)給p1指向的結(jié)點(diǎn)?!裨谳斎氲谝粋€(gè)學(xué)生的數(shù)據(jù)之前,鏈表中沒有結(jié)點(diǎn),所以頭指針head為NULL?!癞?dāng)n=1時(shí),表示是第一個(gè)結(jié)點(diǎn),所以把這個(gè)結(jié)點(diǎn)的指針p1的值賦給head,head就指向了鏈表的頭部。●輸入的學(xué)號(hào)為0表示學(xué)生數(shù)據(jù)已經(jīng)讀完,鏈表建成,不再繼續(xù)建立新結(jié)點(diǎn)的循環(huán)?!竦?個(gè)結(jié)點(diǎn)建立以后,為了建立下一個(gè)結(jié)點(diǎn),再用malloc函數(shù)開辟一個(gè)結(jié)點(diǎn),并且用p1指向這個(gè)新結(jié)點(diǎn),如圖7.5(a)所示;圖7.8建立第2個(gè)結(jié)點(diǎn)●接著讀入第二個(gè)學(xué)生的數(shù)據(jù),由于讀入的學(xué)號(hào)非0,所以第二次進(jìn)入建立結(jié)點(diǎn)的循環(huán),由于結(jié)點(diǎn)數(shù)n不為1,所以將p1的值賦給p2->next,使第一個(gè)結(jié)點(diǎn)連到了第二個(gè)結(jié)點(diǎn),如圖7.7(b)所示?!袢缓?,將p1的值賦給p2,使第二個(gè)結(jié)點(diǎn)的p1、p2兩個(gè)指針又回到圖7.7第一個(gè)結(jié)點(diǎn)剛建立的狀態(tài),準(zhǔn)備建立下一個(gè)結(jié)點(diǎn)?!袢绱酥芏鴱?fù)始,建立更多節(jié)點(diǎn)。
圖7.9建立第3個(gè)結(jié)點(diǎn)圖7.7建立第4個(gè)結(jié)點(diǎn)
當(dāng)讀入的學(xué)號(hào)為0時(shí),表示學(xué)生數(shù)據(jù)已經(jīng)輸入完畢,所以不再進(jìn)入建立新結(jié)點(diǎn)的while循環(huán),而置p2->next為NULL,表示剛才建立的結(jié)點(diǎn)是尾結(jié)點(diǎn),此時(shí),雖然p1指向新開辟的結(jié)點(diǎn),但是這個(gè)“新結(jié)點(diǎn)”并不包含在鏈表之內(nèi),從鏈表中不可能找到這個(gè)結(jié)點(diǎn)。建立動(dòng)態(tài)鏈表函數(shù)如下:#defineNULL0#defineLENsizeof(structstudent)/*sizeof是求字節(jié)運(yùn)算符函數(shù),所以本行定義的LEN代表structstudent類型數(shù)據(jù)的長(zhǎng)度*/structstudent{longnum;floatscore;structstudent*next;};intn;/*全局變量,表示結(jié)點(diǎn)個(gè)數(shù)*/structstudent*creat(void) /*定義指針函數(shù),建立單向動(dòng)態(tài)鏈表,函數(shù)返回一個(gè)指向鏈表頭的指針。其它函數(shù)中調(diào)用時(shí)只要寫creat();即可*/{structstudent*head,*p1,*p2;/*設(shè)置3個(gè)指針變量head、p1和p2*/n=0; /*n是結(jié)點(diǎn)計(jì)數(shù)器*/p1=p2=(structstudent*)malloc(LEN);/*在動(dòng)態(tài)存區(qū)分配長(zhǎng)度為 LEN的存區(qū),并返回首地址,指向structstudent類型數(shù)據(jù)的指針*/head=NULL;scanf(“%ld,%f”,&p1->num,*p1->score);while(p1->num!=0)/*當(dāng)學(xué)號(hào)不為0時(shí),進(jìn)入建立結(jié)點(diǎn)循環(huán)*/{n=n+1;if(n==1)head=p1;/*把第一個(gè)結(jié)點(diǎn)的首地址賦給頭指針*/elsep2->next=p1;/*使當(dāng)前結(jié)點(diǎn)的p2->next指向下一個(gè)結(jié)點(diǎn)*/p2=p1; /*使新開辟結(jié)點(diǎn)的p1、p2回到結(jié)點(diǎn)剛建立的狀態(tài)*/p1=(structstudent*)malloc(LEN);/*結(jié)點(diǎn)建成后,開辟新的結(jié)點(diǎn)*/scanf(“%ld,,%f”,&p1->num,&p1->score);/*讀入下一學(xué)生*/}p2->next=NULL;/*置p2->next為NULL,表示剛建結(jié)點(diǎn)是尾結(jié)點(diǎn)*/return(head);/*本函數(shù)條用結(jié)束后,給主調(diào)函數(shù)返回鏈表的頭指針*/}
7.4.4對(duì)鏈表的刪除
所謂刪除動(dòng)態(tài)鏈表的某個(gè)結(jié)點(diǎn),其實(shí)并不是真的從內(nèi)存中把這個(gè)結(jié)點(diǎn)抹掉,只是撤銷原來的連接關(guān)系,把這個(gè)結(jié)點(diǎn)從鏈表中分離出去。
如果刪除制定學(xué)號(hào)(num)的節(jié)點(diǎn),就從頭結(jié)點(diǎn)開始,逐個(gè)比較每個(gè)結(jié)點(diǎn)的num是否等于該指定的學(xué)號(hào),如果相等就將該結(jié)點(diǎn)刪除,否則就比較下一個(gè)結(jié)點(diǎn),直到檢查到鏈表的表尾為止?!裣仍O(shè)置2個(gè)指針p1和p2,使p1指向第1個(gè)結(jié)點(diǎn)?!袷紫葯z查第一個(gè)結(jié)點(diǎn)●如果要?jiǎng)h除的結(jié)點(diǎn)不是第1個(gè)結(jié)點(diǎn),首先將p1的值賦給p2,使p2指向剛才檢查過的結(jié)點(diǎn),然后使p1指向下一個(gè)結(jié)點(diǎn)(即p1=p1->next),如圖7.11(b)●如此一次一次地使指針后移,直到查到要?jiǎng)h除的結(jié)點(diǎn)或者一直查到表尾都沒有找到要?jiǎng)h除的結(jié)點(diǎn)為止。
查找需要?jiǎng)h除的結(jié)點(diǎn)如果找到了要?jiǎng)h除的結(jié)點(diǎn),而且是第一個(gè)結(jié)點(diǎn),則將p1->next賦給head,如圖7.11(c),于是第1個(gè)結(jié)點(diǎn)就被刪除了(實(shí)際是是和鏈表脫離了,不再是鏈表的一部分)。刪除找到的結(jié)點(diǎn)如果要?jiǎng)h除的結(jié)點(diǎn)不是第一個(gè)結(jié)點(diǎn),譬如查到第2個(gè)結(jié)點(diǎn)時(shí)(所以現(xiàn)在p1指向第2個(gè)結(jié)點(diǎn)),發(fā)現(xiàn)它是要?jiǎng)h除的結(jié)點(diǎn),則將p1->next賦給則將p2->next,如圖7.11(d),于是第1個(gè)結(jié)點(diǎn)不再指向第2個(gè)結(jié)點(diǎn),而是指向第3個(gè)結(jié)點(diǎn)了,因此把第2個(gè)結(jié)點(diǎn)與鏈表脫離了。找不到要?jiǎng)h除的結(jié)點(diǎn)如果直到查到表尾都沒有找到要?jiǎng)h除的結(jié)點(diǎn),則輸出“找不到要?jiǎng)h除的結(jié)點(diǎn)”??毡砣绻檎盏逆湵硪粋€(gè)結(jié)點(diǎn)都沒有,即頭指針位空,完全是個(gè)空表,則輸出“空表”信息。刪除結(jié)點(diǎn)的算法框圖刪除結(jié)點(diǎn)的函數(shù)如下:structstudent*del(structstudent*head,longnum)/*head 是頭指針,num是要?jiǎng)h除的結(jié)點(diǎn)學(xué)號(hào)*/{structstudent*p1,*p2;if(head==NULL){printf(“\nemptylist!\n”);gotoend;} /*輸出空表信息*/p1=head;while(num!=p1->num&&p1->next!=NULL){p2=p1;p1=p1->next;} /*p1向后移一個(gè)結(jié)點(diǎn)*/if(num==p1->num) /*找到要?jiǎng)h除結(jié)點(diǎn)*/{if{p1==head)head=p1->next;/*刪除了第一結(jié)點(diǎn)*/elsep2->next=p1->next;/*不是第1結(jié)點(diǎn)*/printf(“%ldhasbeendeleted\n”,num);n=n-1;}elseprintf(“%ldhasnotbeenfound!\n”,num);/*顯示找 不到信息*/end:return(head);}7.4.5對(duì)鏈表的插入操作
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 合伙銷售茶葉合同范本
- 農(nóng)業(yè)維護(hù)協(xié)議合同范本
- 辦公耗材批發(fā)合同范本
- 醫(yī)院保潔耗材合同范本
- 合同范本由誰出
- 售賣蛋糕合同范本
- 受托付款合同范例
- 員工社保合同范本
- 合同范本個(gè)可以獲取
- 廚師勞務(wù)派遣服務(wù)合同范本
- 2025年榆林市公共交通總公司招聘(57人)筆試參考題庫(kù)附帶答案詳解
- 醫(yī)院培訓(xùn)課件:《多發(fā)性骨髓瘤》
- 【新】部編人教版小學(xué)4四年級(jí)《道德與法治》下冊(cè)全冊(cè)教案
- 2025年湖南省長(zhǎng)沙市單招職業(yè)傾向性測(cè)試題庫(kù)及參考答案
- 《產(chǎn)業(yè)轉(zhuǎn)移》課件:機(jī)遇與挑戰(zhàn)
- 十八項(xiàng)核心制度培訓(xùn)課件
- 2024年遠(yuǎn)程教育行業(yè)市場(chǎng)運(yùn)營(yíng)現(xiàn)狀及行業(yè)發(fā)展趨勢(shì)報(bào)告
- 2025年2月上海市高三聯(lián)考高考調(diào)研英語試題(答案詳解)
- 三好學(xué)生競(jìng)選12
- 2024-2025學(xué)年六年級(jí)上學(xué)期數(shù)學(xué)第三單元3.1-搭積木比賽(教案)
- DeepSeek從入門到精通
評(píng)論
0/150
提交評(píng)論