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