寫(xiě)在前面:
- 1.首先鏈表的本質(zhì)只是一種特殊的結(jié)構(gòu)體,所以C語(yǔ)言當(dāng)作并沒(méi)有現(xiàn)成的函數(shù)去幫助你延長(zhǎng)鏈表或者幫助你輸出鏈表,所有的東西全部需要靠你自己.
- 2.學(xué)習(xí)鏈表之前需要的預(yù)備知識(shí):結(jié)構(gòu)體,指針,動(dòng)態(tài)內(nèi)存分配.
P.S.鏈表本身并不需要?jiǎng)討B(tài)內(nèi)存分配,但是可以確保你在函數(shù)中生成的鏈表所占用的內(nèi)存不會(huì)在函數(shù)結(jié)束后被釋放.
PP.SS.如果你看不懂上面那句話(huà),不明白我在說(shuō)什么可以學(xué)習(xí)一下C語(yǔ)言中變量的生存周期和動(dòng)態(tài)內(nèi)存分配.
1.什么是鏈表
在之前已經(jīng)說(shuō)過(guò)鏈表不過(guò)是定義特殊的結(jié)構(gòu)體
先來(lái)在邏輯上理解一下鏈表
這里借用一下另一個(gè)blog的圖片:https://blog.csdn.net/morixinguan/article/details/68951912
image
鏈表這種結(jié)構(gòu)體的特殊之處在于有一個(gè)*next.
*next為一個(gè)指向這種結(jié)構(gòu)體的下一個(gè)節(jié)點(diǎn)的指針,這種結(jié)構(gòu)體中均有一個(gè)*next
當(dāng)你訪(fǎng)問(wèn)首位鏈表時(shí)*next中存放了鏈表中的下一個(gè)節(jié)點(diǎn)的地址如此將本互不相連的若干個(gè)結(jié)構(gòu)體連接了起來(lái),同時(shí)這些結(jié)構(gòu)體數(shù)據(jù)類(lèi)型又相同如此起到了一種類(lèi)似于數(shù)組卻比數(shù)組更加方便的數(shù)據(jù)類(lèi)型,被稱(chēng)為鏈表.
這條鏈從Head開(kāi)始(即鏈表第一個(gè)節(jié)點(diǎn)的地址)最后一個(gè)節(jié)點(diǎn)依然有*next不過(guò)它的值等于NULL.
2.如何定義一個(gè)鏈表
如下是一個(gè)鏈表的定義.
struct student {
int num,score;//這就是我們所說(shuō)的數(shù)據(jù)域
struct student *next;
};//定義一個(gè)結(jié)構(gòu)體(鏈表)
數(shù)據(jù)的多少名稱(chēng)大小都可以自己定義.
3.如何使用
定義好了鏈表接下來(lái)便是如何使用它
這里我便以例代講:
題目
#include<stdio.h>
#include<malloc.h>
/* User Code Begin(考生可在本行后添加代碼,定義程序中使用的結(jié)構(gòu)體類(lèi)型、聲明自定義函數(shù)的原型,行數(shù)不限) */
struct student {
int num,score;
struct student *next;
};//定義一個(gè)結(jié)構(gòu)體(鏈表)
struct student *creat(void);
struct student *merge(struct student*a,struct student*b);
/* User Code End(考生添加代碼結(jié)束) */
/* print以規(guī)定的格式完成遍歷顯示指定的鏈表 */
void print(char *Info, struct student *Head);
int main(void)
{
struct student *ah, *bh;
printf("創(chuàng)建鏈表A,請(qǐng)輸入學(xué)號(hào)及成績(jī)(均輸入為0時(shí)表示停止):\n");
ah = creat();
printf("\n創(chuàng)建鏈表B,請(qǐng)輸入學(xué)號(hào)及成績(jī)(均輸入為0時(shí)表示停止):\n");
bh = creat();
print("\n鏈表A:", ah);
print("\n鏈表B:", bh);
ah = merge(ah, bh);
print("\n鏈表A、B合并后:", ah);
return 0;
}
void print(char *Info, struct student *Head)
{
printf("%s", Info);
while (Head != NULL)
{
printf("%d,%d ", Head->num, Head->score);
Head = Head->next;
}
}
/* User Code Begin(考生在此后完成自定義函數(shù)的設(shè)計(jì),行數(shù)不限) */
struct student *creat(void)//定義函數(shù)建立鏈表
{
struct student *Head,*p1,*p2;//*Head是這個(gè)鏈表的首地址單獨(dú)定義并且保存下來(lái)
int n=1;
Head=p1=p2=(struct student*)malloc(sizeof(struct student));
while(1)
{
printf("學(xué)生 %d: ",n);
scanf("%d %d",&(p2->num),&(p2->score));
//通過(guò)p2保存輸入的數(shù)據(jù)
if(p2->num==0 && p2->score==0)
//普判斷是否要結(jié)束輸入
{
if(n==1)
{
return NULL;//如果沒(méi)有輸入任何數(shù)據(jù)就直接要求結(jié)束輸入就返回NULL
}
return Head;//否則返回鏈表首地址
}
if(Head==NULL)//判斷是否是第一位鏈表
{
//如果是鏈表的第一位的話(huà)執(zhí)行如下操作
Head=p2;//做為Head保存下來(lái)
p1=p2;//同時(shí)賦值給p1方便修改next
p2= (struct student *)malloc(sizeof(struct student));//為p2分配新地址
}
else
{
//如果不是第一位的話(huà):
p1->next=p2;//為p1中next賦值為p2
p2->next=NULL;//將p2中next定義為null
p1=p2;//將p2的地址賦值給p1
p2= (struct student *)malloc(sizeof(struct student));
//為p2分配新的地址
}
n++;
}
}
struct student *merge(struct student *a,struct student *b)//定義函數(shù)合并兩個(gè)鏈表
{
struct student *HEAD=a;
struct student *mid=NULL;
while(1)
{
if(a==NULL)
{
HEAD=b;
return HEAD;
}
if(a->next==NULL)
{
a->next=b;
return HEAD;
}
else
{
a=a->next;
}
}
}