首先感謝ChatGPT給我提供的幫助
進(jìn)入正題
本文作者同為大一新生,寫這篇文章的目的是記錄自己的學(xué)習(xí)經(jīng)歷,以及幫助一些稍有困難的同學(xué)理解數(shù)據(jù)結(jié)構(gòu),能力有限,如有錯(cuò)誤請(qǐng)指出。本文基于嚴(yán)蔚敏老師的《數(shù)據(jù)結(jié)構(gòu)與算法(c語(yǔ)言版 第二版)》創(chuàng)作。(建議學(xué)習(xí)的時(shí)候搭配著書看)
學(xué)習(xí)前提:
1.本文需要有一定的鏈表基礎(chǔ),如果對(duì)鏈表不太了解,建議對(duì)鏈表的結(jié)構(gòu)稍加學(xué)習(xí)之后再來(lái)看。
2.你需要明確知道實(shí)際參數(shù)和形式參數(shù)之間的關(guān)系如果不知道可以看作者的這篇文c語(yǔ)言實(shí)際參數(shù)與形式參數(shù)
實(shí)驗(yàn)內(nèi)容是這樣的
定義一個(gè)包含學(xué)生信息(學(xué)號(hào),姓名,成績(jī))的鏈表,使其具有如下功能:
(1) 根據(jù)指定學(xué)生個(gè)數(shù),逐個(gè)輸入學(xué)生信息;
(2) 逐個(gè)顯示學(xué)生表中所有學(xué)生的相關(guān)信息;
(3) 根據(jù)姓名進(jìn)行查找,返回此學(xué)生的學(xué)號(hào)和成績(jī);
(4) 根據(jù)指定的位置可返回相應(yīng)的學(xué)生信息(學(xué)號(hào),姓名,成績(jī));
(5) 給定一個(gè)學(xué)生信息,插入到表中指定的位置;
(6) 刪除指定位置的學(xué)生記錄;
代碼與講解如下
頭文件
首先你需要的頭文件有
#include <stdio.h> //這個(gè)不需要解釋了吧~~~
#include <stdlib.h> //因?yàn)槲覀冃枰猰alloc函數(shù)分配內(nèi)存和free函數(shù)釋放內(nèi)存,至于這個(gè)頭文件的具體內(nèi)容,建議自己百度
#include <string.h> //和字符串有關(guān)的函數(shù)
鏈表的定義
其次就是鏈表結(jié)點(diǎn)的定義(關(guān)于鏈表的基本構(gòu)造,如果你不會(huì)的話,可以去看看青島大學(xué)王卓老師的課程)
可能有些人會(huì)疑惑,這個(gè)typedef是什么東西,這里之后可能會(huì)出一篇文章詳細(xì)介紹,你可以先簡(jiǎn)單把它理解為:可以為某一類型自定義名稱?;蛘吣阕约撼閭€(gè)時(shí)間細(xì)細(xì)的查一查
typedef struct
{
char no[15]; //學(xué)號(hào)
char name[8]; //名字
int chengji; //成績(jī)
}student;
typedef struct Lnode
{
student date; //數(shù)據(jù)域 ,這是結(jié)構(gòu)體嵌套哦~~在這個(gè)結(jié)構(gòu)體中嵌套了一個(gè)student的結(jié)構(gòu)體
struct Lnode *next; //指針域
}Lnode,*linklist; //指向節(jié)點(diǎn)的指針
輸入
其次就是輸入學(xué)生的信息函數(shù)了
我這里把初始化和輸入寫到了一起。因?yàn)樵谝淮纬绦蛑?,你輸入只有一次?zhí)行,之后的添加都是插入
linklist scanflist() //輸入學(xué)生信息(頭插法)定義一個(gè)返回值是鏈表頭指針的函數(shù)
{
//創(chuàng)建一個(gè)鏈表頭結(jié)點(diǎn)L,并將其next指針設(shè)置為NULL,從而創(chuàng)建一個(gè)空鏈表。
linklist L;
L=(linklist)malloc(sizeof(Lnode));//書中用的是new,但那是c++語(yǔ)法,我們用malloc分配內(nèi)存
L->next=NULL;
//定義一個(gè)結(jié)構(gòu)體指針p,以及變量n存儲(chǔ)學(xué)生數(shù)量,并讀入n。
linklist p; int n,i;
printf("請(qǐng)輸入輸入的學(xué)生數(shù)量:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
p=(linklist)malloc(sizeof(Lnode)); //通過(guò)調(diào)用 malloc() 函數(shù)為指針p分配內(nèi)存空間,大小為結(jié)構(gòu)體Lnode的大小。也就是創(chuàng)建一個(gè)新結(jié)點(diǎn)*P
printf("請(qǐng)輸入學(xué)生信息:\n");
printf("學(xué)號(hào):");
scanf("%s",p->date.no);
printf("姓名:");
scanf("%s",p->date.name); //這里你需要注意一下是字符串輸入,前面不加取地址符
printf("成績(jī):");
scanf("%d",&(p->date.chengji));
p->next=L->next; //使p插入頭結(jié)點(diǎn)后
L->next=p;
}
return L; //返回鏈表的頭指針 L。
}
打印
之后是打印學(xué)生信息的代碼,注意這里的傳參是指針,這里設(shè)計(jì)到實(shí)際參數(shù)和形式參數(shù)的知識(shí)可以看我之前寫的文章文章傳送點(diǎn)我
void printlist(linklist L) //打印學(xué)生信息
{
linklist n; //定義一個(gè)指針n,初始化為鏈表頭節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),也就是第一個(gè)實(shí)際存儲(chǔ)學(xué)生信息的節(jié)點(diǎn)。
n=L->next;
while (n)//使用while循環(huán)遍歷整個(gè)鏈表,當(dāng)n指向的節(jié)點(diǎn)不為空時(shí),執(zhí)行下列操作
{ //打印n指向的結(jié)點(diǎn)里的內(nèi)容
printf("學(xué)號(hào):%s\n姓名:%s\n成績(jī):%d\n",n->date.no,n->date.name,n->date.chengji);
n=n->next;
printf("\n");
}
printf("打印完成,謝謝使用\n");
printf("————————————————————————————\n");
}
插入
接下來(lái)就是插入程序代碼
這里需要用戶輸入插入的結(jié)點(diǎn)位置,所以為了防止用戶輸入一個(gè)超出當(dāng)前鏈表總長(zhǎng)的結(jié)點(diǎn)。我們需要對(duì)鏈表長(zhǎng)度進(jìn)行測(cè)量并與輸入的結(jié)點(diǎn)位置進(jìn)行比對(duì)。
我們?cè)O(shè)置兩個(gè)結(jié)構(gòu)體類型指針p,s
然后我們讓p指針指向第i-1給結(jié)點(diǎn),然后再把s指向的結(jié)點(diǎn)接在后面。之后再調(diào)整結(jié)點(diǎn)中的指針域使其連結(jié)起來(lái)。
void charulist(linklist L)
{
int i,j,n;
linklist s,p; //定義結(jié)構(gòu)體指針p和s
p=L;
while (p!=NULL) //測(cè)量一下現(xiàn)在鏈表的長(zhǎng)度
{ //除非p為空while循環(huán)繼續(xù)
p=p->next; //p指向下一個(gè)結(jié)點(diǎn)
n++; //n加1
}
printf("請(qǐng)輸入插入的結(jié)點(diǎn)的位置");
scanf("%d",&i);
while (i>n)
{
printf("輸入的結(jié)點(diǎn)超過(guò)總長(zhǎng),請(qǐng)重新輸入");
scanf("%d",&i);
}
p=L;j=1;
while (p&&(j<i)) //讓p指向第i-1個(gè)結(jié)點(diǎn)
{
p=p->next;
++j;
}
s=(linklist)malloc(sizeof(Lnode)); //用s指向準(zhǔn)備插入的結(jié)點(diǎn),并給它分配一個(gè)內(nèi)存空間
printf("請(qǐng)輸入學(xué)生信息:\n"); //后面的內(nèi)容和輸入同理
printf("學(xué)號(hào):");
scanf("%s",s->date.no);
printf("姓名:");
scanf("%s",s->date.name);
printf("成績(jī):");
scanf("%d",&s->date.chengji);
s->next=p->next;
p->next=s;
printf("信息插入成功\n");
printf("——————————————————————————\n");
}
刪除
然后是刪除函數(shù)
大體和插入一樣,都是找到想要的結(jié)點(diǎn),之后的操作改成釋放內(nèi)存就好(free函數(shù))
void deletelist(linklist L)
{
int i,n=0,j;
linklist p,q;
p=L->next;
while (p!=NULL)
{
p=p->next;
n++;
}
printf("請(qǐng)輸入要?jiǎng)h除學(xué)生的位置結(jié)點(diǎn):");
scanf("%d",&i);
while(n<i)
{
printf("輸入的結(jié)點(diǎn)值超過(guò)總數(shù),請(qǐng)重新輸入要?jiǎng)h除學(xué)生的位置結(jié)點(diǎn):");
scanf("%d",&i);
}
p=L; j=1;
while((p->next)&&(j<i)) //注意這里p是指向第i-1個(gè)結(jié)點(diǎn)的
{//這里和上面其實(shí)還有給小細(xì)節(jié),你自己細(xì)細(xì)比對(duì)一下,然后體會(huì)一下為什么(自己思考一下)
p=p->next;
++j;
} //到這為止上面都是一樣的
q=p->next; //q指向第i跟結(jié)點(diǎn)
p->next=q->next; //p的指針域改為指向第i+1個(gè)結(jié)點(diǎn)(跳過(guò)第i個(gè),也就是p指向的)
free(q); //利用free函數(shù)釋放內(nèi)存
printf("刪除成功!\n");
printf("————————————————————————\n");
}
查找
輸入要查找的學(xué)生姓名,然后將該值存儲(chǔ)在字符數(shù)組name中。
用p指針指向鏈表中第一個(gè)節(jié)點(diǎn)的位置。
通過(guò)while循環(huán)遍歷鏈表,每次使用strcmp函數(shù)比較字符串是否相同,如果不同,則將 p 指向下一個(gè)節(jié)點(diǎn),同時(shí)將計(jì)數(shù)j加1。如果相同,跳出循環(huán)。
如果找到了目標(biāo)節(jié)點(diǎn),則打印出該節(jié)點(diǎn)中的學(xué)號(hào)和成績(jī)信息。否則,打印出“該表中沒(méi)有該學(xué)生的信息”。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-772720.html
void findlist(linklist L)//查找
{
char name[10];
int j=1;
linklist p;
printf("請(qǐng)輸入查找學(xué)生的姓名:");
scanf("%s",name);
p=L->next;
while(p&&strcmp(p->date.name,name)!=0) //這里是strcmp函數(shù)是字符串的函數(shù),如果忘記了可以去復(fù)習(xí)一下
{//它用來(lái)比較字符串的大小是否相同(當(dāng)然這里的大小是字典序而不是長(zhǎng)度,別弄混了)
p=p->next;
j++;
}//跳出循環(huán)的條件分別是:p為空(走到鏈表底了)和找到了符合條件的結(jié)點(diǎn)
if(p)//如果p不為空(也就是p找到了)
printf("該學(xué)生的信息:\n學(xué)號(hào):%s\n成績(jī):%d\n",p->date.no,p->date.chengji);
else
printf("該表中沒(méi)有該學(xué)生的信息。");
}
主函數(shù)
終于完活了文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-772720.html
int main()
{
linklist L;
int k,n;
L=scanflist();
printf("輸入成功\n");
printf("——————————————————————————————\n");
while (1)
{
printf("使用服務(wù)輸入1,結(jié)束程序輸入0\n");
scanf("%d",&k);
if(k==1)
{
printf("1-打印所有學(xué)生信息\n2-插入學(xué)生信息\n3-刪除學(xué)生信息\n4-姓名查找學(xué)生\n0-退出\n");
printf("請(qǐng)輸入使用的項(xiàng)目\n");
scanf("%d",&n);
switch (n)
{
case 0:printf("已返回上一界面\n");break;
case 1:printlist(L);break;
case 2:charulist(L);break;
case 3:deletelist(L);break;
case 4:findlist(L);break;
}
}
else
{ if(k==0)
{
printf("謝謝使用");break;
}
else
printf("指令錯(cuò)誤,請(qǐng)重新輸入\n");
}
}
}
謝謝閱讀,如果對(duì)你有幫助的話可以點(diǎn)個(gè)關(guān)注點(diǎn)個(gè)贊哦
到了這里,關(guān)于c語(yǔ)言數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn):鏈表實(shí)現(xiàn)學(xué)生信息的儲(chǔ)存的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!