创建
首先链表这个数据结构的结构体由两个部分组成,分别是数据域和指针域,也就是存放数据的变量和指针
struct student{
char name[30]; //数据域
float number; //数据域
struct student *pNext; //指针域
};
链表的创建,就是在创建节点(malloc)和输入数据的同时让每个节点(结构体)都连接起来,连接的方式就是靠指针域中的指针,让每个结点的pNext都指向下一个节点,最后一个节点没节点可指的呀,那就让最后一个节点的指针(pNext)指向空(NULL)
这样,每个节点都连在了一起,就形成了一个长链,链表就创建好啦
struct student *create(){
struct student *pHead=NULL; //头节点,指向第一个结构体
struct student *pNew,*pEnd; //新节点和最后一个节点
pNew=pEnd=(struct student*)malloc(sizeof(struct student)); //给新节点和最后一个节点分配内存
printf("名字 学号:");
scanf("%s %f",&pNew->name,&pNew->number); //输入数据
/*判断当数据中的number等于0时停止分配新节点*/
while(pNew->number!=0){
len++; //长度(将会在后面完整代码中出现,这是个全局变量)
if(len==1){
pNew->pNext=NULL; //当长度等于1时让新节点的指针指向空(NULL)
pEnd=pNew;
pHead=pNew;
}
else{
pNew->pNext=NULL; //当长度大于1时新节点指针指向空
pEnd->pNext=pNew; //最后一个节点指向新节点
pEnd=pNew;
}
pNew=(struct student*)malloc(sizeof(struct student)); //分配新节点
scanf("%s %f",&pNew->name,&pNew->number);
}
free(pNew); //将多分配出的节点释放掉
return pHead; //返回链表的的头节点
}
或者还可以这样创建
struct student *create(){
struct student *pHead,*pNew,*p;
pNew=(struct student*)malloc(sizeof(struct student));
printf("输入名字 学号:\n");
scanf("%s %f",&pNew->name,&pNew->number);
pNew->pNext=NULL;
pHead=pNew;
p=pNew;
pNew=(struct student*)malloc(sizeof(struct student));
scanf("%s %f",&pNew->name,&pNew->number);
while(pNew->number!=0){
p->pNext=pNew;
p=p->pNext;
pNew=(struct student*)malloc(sizeof(struct student));
scanf("%s %f",&pNew->name,&pNew->number);
}
p->pNext=NULL;
free(pNew);
return pHead;
}
遍历
知道如何创建了,下一步就是遍历
遍历的话就很简单了,就是用循环让指针指向下一个节点然后输出数据域里的数据就好了
void print(struct student *pHead){ //遍历函数,传入头节点
struct student *tep; //遍历指针
int i=1; //长度
tep=pHead; //让遍历指针指向头节点
printf("----------共%d个成员----------\n",len); //输出长度
/*当指针等于NULL,停止循环*/
while(tep!=NULL){
printf("No.%d名字:%s\n",i,tep->name); //输出数据
printf("学号:%g\n\n",tep->number); //输出数据
i++; //第i个数据
tep=tep->pNext; //指向下一个节点
}
printf("\n\n");
}
加入新节点
基本的创建和遍历学会后,现在来学如何在操作过程中加入新结点
1.在头节点后加入
头节点后好说,先在新开辟的结构体里输入新数据,然后让新节点的pNext指向头节点的pNext,再让头节点的pNext指向新节点,这样,新的数据就被加入到了头节点后面
struct student *addah(struct student *pHead){ //加入函数,传入头节点
struct student *pNew,*tep; //新的节点(这里的*tep没有实际意义,可不要)
pNew=(struct student*)malloc(sizeof(struct student)); //为新节点开辟内存
printf("姓名 学号:");
scanf("%s %f",&pNew->name,&pNew->number); //输入新数据
pNew->pNext=pHead->pNext; //让新节点的pNext指针指向头节点的pNext
pHead->pNext=pNew; //让头节点的pNext指向新节点
len+=1; //长度加1
return pHead; //返回头节点
}
2.在链表末尾加入
这个同样非常简单,方法就是先创建一个结构体指针(*tep)和新节点(*pNew),先输入新节点的数据,接着让 tep指向头节点,然后让 tep类似于遍历时那样一路往下指,直到 tep指向了最后一个节点为止, 最后让 *tep的pNext指向新节点,新节点的pNext等于NULL就可以啦
struct student *addend(struct student *pHead){ //加入函数,传入头节点
struct student *tep,*pNew; //一个用来指向原链表最后一个节点的结构体指针(*tep)和新节点(*pNew)
pNew=(struct student*)malloc(sizeof(struct student)); //为新节点开辟内存
tep=pHead; //让tep指向头节点用来找原链表的最后一个节点
printf("姓名 学号:");
scanf("%s %f",&pNew->name,&pNew->number); //输入新数据
pNew->pNext=NULL; //新节点的pNew指向NULL
/*当tep的pNext不是NULL是,tep指向tep的下一个节点,直到tep的pNext是NULL*/
while(tep->pNext!=NULL){
tep=tep->pNext;
}
tep->pNext=pNew; //原链表的最后一个节点的pNext指向新节点
len+=1; //长度加1
return pHead; //返回头节点
}
3.指定位置加入
这个就稍微多一些,加入方法就是先创建两个结构体指针( *pBefore和 *p)还有一个新节点(*pNew),一个要加入的位置数据(int location)和记录长度数据(int n=2)
先说指针部分,第一个指针pBefore是用来指向pHead的指针,至于before是在另一个指针p之前的意思,那么,第二个指针p就是pBefore的pNext所指向的节点,这样做,是为了能让新节点能够加入到两个相邻节点之间(不是头节点后,也不是末尾位置),加入方式和加入头节点后的方法一样,首先让新节点的pNext指向pBefore的pNext,然后再让pBefore的pNext指向新节点,这样,就完成了在两个相邻节点之间加入,这里只是把pBefore的pNext换成了p
然后就是那两个整形了,location是你要加入的位置,n就是去寻找那个位置,那为什么等于2?原因是当n=1的时候所加入的数据会是你输入的位置的下一位,比如你想要加入到第3个位置,如果n=1,那实际加入的位置就是4,所以n=2,从2开始
struct student *addlocation(struct student *pHead){ //加入函数,传入头节点
struct student *pBefore,*p,*pNew; //一个用于指向头节点的指针(*pBefore)和一个头节点下一个节点的指针(*p),还有一个新节点(*pNew)
p=pHead->pNext; //p指向头节点的下一个节点
pBefore=pHead; //pBefore指向头节点
int location,n=2; //要加入的指定位置(location)和用于寻找位置(n=2)的整形
pNew=(struct student*)malloc(sizeof(struct student)); //为新节点开辟内存
printf("姓名 学号:");
scanf("%s %f",&pNew->name,&pNew->number); //输入新数据
printf("要加入的位置:");
scanf("%d",&location); //输入要加入的位置
/*当要加入的位置是1时,直接让新节点的pNext指向头节点,然后返回pNew*/
if(location==1){
pNew->pNext=pHead;
len+=1; //长度加1
return pNew;
}
/*当要加入的位置是末尾时,请参考上面的第二种加入方法*/
if(location==(len+1)){
while(p->pNext!=NULL){
p=p->pNext;
}
pNew->pNext=NULL;
p->pNext=pNew;
len+=1; //长度加1
return pHead;
}
/*当要加入的位置不是开头和结尾时*/
else{
/*用n去寻找location是哪个位置*/
while(n!=location){
n++;
p=p->pNext; //让p指向p的下一个节点
pBefore=pBefore->pNext; //让pBefore指向pBefore的下一个节点
}
/*找到要加入的位置后*/
pNew->pNext=p; //让新的节点指向相邻节点的后一个节点
pBefore->pNext=pNew; //让相邻节点的前一个节点指向新节点
len+=1; //长度加1
return pHead; //返回头节点
}
}
删除
最后一个,如何在操作过程中删除某一个节点,同样也要去寻找位置,方法类似于加入方法的第三个,所以,现在来说说如何删除
删除的方法就是让被删除的上一个节点的pNext指向被删除的下一个节点然后将其free掉,两个指针一个before(等同于上面的pBefore),一个search(等同于上面的p),这里的search就是要被free的节点
struct student *del(struct student *pHead){ //删除函数,传入头节点
/*指针和整形数据类似于加入方法第三个*/
struct student *before,*search; //search是要被释放的节点,before是被释放节点的前一个
int lead,i=2;
before=pHead;
search=pHead->pNext;
printf("输入要删除的位置:");
scanf("%d",&lead);
/*寻找方式一样*/
while(1){
if(lead==1){
len--;
return search;
}
if(i==lead){
before->pNext=search->pNext; //before的pNext跳过search指向search的下一个节点(search的pNext)
free(search); //释放
break;
}
i++;
before=before->pNext; //让before等于它下一个节点
search=search->pNext; //让search等于它下一个节点
}
len--; //长度减1
return pHead; //返回头节点
}
完整代码
#include <stdio.h>
#include <stdlib.h>
int len; //链表长度
struct student{
char name[30];
float number;
struct student *pNext;
};
/*创建*/
struct student *create(){
struct student *pHead=NULL;
struct student *pNew,*pEnd;
pNew=pEnd=(struct student*)malloc(sizeof(struct student));
printf("名字 学号:");
scanf("%s %f",&pNew->name,&pNew->number);
while(pNew->number!=0){
len++;
if(len==1){
pNew->pNext=NULL;
pEnd=pNew;
pHead=pNew;
}
else{
pNew->pNext=NULL;
pEnd->pNext=pNew;
pEnd=pNew;
}
pNew=(struct student*)malloc(sizeof(struct student));
scanf("%s %f",&pNew->name,&pNew->number);
}
free(pNew);
return pHead;
}
/*头表后加入*/
struct student *addah(struct student *pHead){
struct student *pNew,*tep;
pNew=(struct student*)malloc(sizeof(struct student));
printf("姓名 学号:");
scanf("%s %f",&pNew->name,&pNew->number);
pNew->pNext=pHead->pNext;
pHead->pNext=pNew;
len+=1;
return pHead;
}
/*加入结尾*/
struct student *addend(struct student *pHead){
struct student *tep,*pNew;
pNew=(struct student*)malloc(sizeof(struct student));
tep=pHead;
printf("姓名 学号:");
scanf("%s %f",&pNew->name,&pNew->number);
pNew->pNext=NULL;
while(tep->pNext!=NULL){
tep=tep->pNext;
}
tep->pNext=pNew;
len+=1;
return pHead;
}
/*指定位置删除*/
struct student *del(struct student *pHead){
struct student *before,*search;
int lead,i=2;
before=pHead;
search=pHead->pNext;
printf("输入要删除的位置:");
scanf("%d",&lead);
while(1){
if(lead==1){
len--;
return search;
}
if(i==lead){
before->pNext=search->pNext;
free(search);
break;
}
i++;
before=before->pNext;
search=search->pNext;
}
len--;
return pHead;
}
/*指定位置加入*/
struct student *addlocation(struct student *pHead){
struct student *pBefore,*p,*pNew;
p=pHead->pNext;
pBefore=pHead;
int location,n=2;
pNew=(struct student*)malloc(sizeof(struct student));
printf("姓名 学号:");
scanf("%s %f",&pNew->name,&pNew->number);
printf("要加入的位置:");
scanf("%d",&location);
if(location==1){
pNew->pNext=pHead;
len+=1;
return pNew;
}
if(location==(len+1)){
while(p->pNext!=NULL){
p=p->pNext;
}
pNew->pNext=NULL;
p->pNext=pNew;
len+=1;
return pHead;
}
else{
while(n!=location){
n++;
pBefore=pBefore->pNext;
}
pNew->pNext=pBefore->pNext;
pBefore->pNext=pNew;
len+=1;
return pHead;
}
}
/*遍历*/
void print(struct student *pHead){
struct student *tep;
int i=1;
tep=pHead;
printf("----------共%d个成员----------\n",len);
while(tep!=NULL){
printf("No.%d名字:%s\n",i,tep->name);
printf("学号:%g\n\n",tep->number);
i++;
tep=tep->pNext;
}
printf("\n\n");
}
int main(){
struct student *pHead;
pHead=create();
print(pHead);
pHead=addah(pHead);
print(pHead);
pHead=addend(pHead);
print(pHead);
pHead=addlocation(pHead);
print(pHead);
pHead=del(pHead);
print(pHead);
}