malloc函数和free函数通常配对使用,malloc如果没有free释放内存可能会造成“内存泄漏”
![](https://i-blog.csdnimg.cn/blog_migrate/3869d0048be17aa6035f10788125d2fc.webp?x-image-process=image/format,png)
创建链表并添加节点
一、创建链表流程
(1)创建一个链表需要三个指针:指针(pHead),尾指针(pEnd),新指针(pNew)
(2)刚开始链表中一个结点都没有,可用malloc申请内存,动态创建1个结点,令pNew指向它
(3)输入数据后,目前这个新结点又是头结点,也是最后一个结点,所以要令pHead和pEnd也指向它。第一个结点通常需要特殊处理,所以将它放在循环外面建立
(4)剩下3个结点有相同规律,可用(5)到(7)步的循环进行处理:
(5)新建结点给pNew,输入数据
(6)使最后一个结点pEnd的下一结点next指向这个新结点,形成兄弟关系
(7)将新结点pNew设为最后一个结点pEnd
(8)循环结束
(9)不再添加结点,要使最后一个结点pEnd的指针指向NULL
(10)返回头指针pHead
定义全局变量n,各模块函数都可以使用
1、create函数创建链表:struct student* create()
创建链表并输入四个节点
算法思路:让pNew指向新开辟的结点,pEnd指向链表中最后一个结点,把pNew所指的结点连接在pEnd所指结点的后面,即pEnd->next=pNew; 。
(1)头指针(pHead) 尾指针(pEnd) 新指针(pNew):struct student *pHead,*pEnd,*pNew;。全局变量赋初值0:n=0;.
(2)malloc函数开辟新单元给尾指针和新指针, struct student*是使malloc返回的指针转化为struct student类型数据的指针(*不可省略,否则就转换成struct student类型,而不是指针类型), sizeof求字节数:pEnd=pNew=(struct student*)malloc(sizeof(struct student)); 由于编译系统能实现隐式的类型转换,故可以写成pEnd=pNew=malloc(sizeof(struct student));
输入第一个个学生名字和成绩:scanf("%s%d",pNew->name,&pNew->age);
(3)头指针为NULL
(4)循环:
while(pNew!=0)
{
n=n+1;
if(n==1)
pHead=pNew;
else
pEnd->next=pNew;
pEnd=pNew; //使新节点成为最后一个节点
pNew=(struct student*)malloc(sizeof(struct student));//开辟动态存储区,把起始地址赋给pNew
scanf("%s%d",pNew->name,&pNew->age); //输入后面学生名字成绩
}
(5)pEnd->next=pNew; //使最后一个节点的下一节点指针指向新节点
pEnd->next=NULL; //最后一个节点的下一节点指针为空
return pHead; //返回头指针
2、print函数输出链表
相对其它操作,输出链表结点的操作比较简单,用一个临时指针通过循环不停地指向下一结点即可。
print函数输出链表所有结点:
void print(struct student *pHead)
{
struct student *p;
p=pHead; //使p指向第一个结点
if(pHead!=NULL)
do
{
printf("name:%s , age:%d \n",p->name,p->age);
p=p->next;
}while(p!=NULL);
}
3、del函数删除结点
删除结点时通常会进行结点查找,找到符合条件的结点再进行删除操作。
在本程序中找到第3个结点为要删除的结点,再令第2个结点的下一结点指针指向第4个结点,第3个结点就完成了自然脱链动作。
del函数删除指定姓名的结点
4、insert函数插入结点
插入的意思是把结点插入至链表中间,插入方法有“前插”和“后插”法,前插就是找到目标结点后,在它前面插入新结点,后插就是在其后面插入。本程序中演示的是前插法。有个例外的是:如果未找到指定结点,会将新结点添加到链表最后。
insert函数插入一个新结点在指定姓名之前
#include<stdio.h>
#include<stdlib.h>
struct student
{
char name[9];
int age;
struct student*next; //指向下一个节点,指向自身的指针
};
int n; //定义全局变量,各模块函数都可以使用
//创建链表、节点:返回链表头指针
struct student* create()
{
struct student *pHead,*pEnd,*pNew; //头指针 尾指针 新指针
//建立链表及第一个节点。。因为第一个节点是头结点,所以要放在循环外面特殊处理
pEnd=pNew=(struct student*)malloc(sizeof(struct student)); //malloc函数分配内存,需要加头文件#include<stdlib.h>
scanf("%s%d",pNew->name,&pNew->age); //取结构成员的地址,首数组为该数组的地址,故scanf不需要加&
//建立后面链表节点
while(pNew->age!=0)
{
n=n+1;
if(n==1)
pHead=pNew;
else
pEnd->next=pNew;
pEnd=pNew; //使新节点成为最后一个节点
pNew=(struct student*)malloc(sizeof(struct student));//开辟动态存储区,把起始地址赋给pNew
scanf("%s%d",&pNew->name,&pNew->age); //输入后面学生名字成绩
}
pEnd->next=pNew; //使最后一个节点的下一节点指针指向新节点
pEnd->next=NULL; //最后一个节点的下一节点指针为空
return pHead; //返回头指针
}
//输出链表
void print(struct student *pHead)
{
struct student *p;
p=pHead; //使p指向第一个结点
if(pHead!=NULL)
do
{
printf("name:%s , age:%d \n",p->name,p->age);
p=p->next;
}while(p!=NULL);
}
void del(struct student *pHead,int ilndex) //删除节点
{
struct student *pFront,*pBack;//前节点,后节点
int i=0;
pBack=pHead; //后节点指向头结点
pFront=pHead; //前节点指向头结点的下一节点
for(i=0;i<ilndex-1;i++)
{
pFront=pBack;
pBack=pBack->next;
}
pFront->next=pBack->next; //后节点设为前节点
free(pBack);
n--; //前节点设为前节点的下一节点
}
void insert(struct student *pHead,int ipoint)
{
struct student *pFront,*pBack,*pNew;
int i;
pNew=(struct student*)malloc(sizeof(struct student));
printf("Please input the new node's name and age:\n");
scanf("%s%d",pNew->name,&pNew->age);
pBack=pFront;
pFront=pHead->next;
for(i=0;i<ipoint-1;i++)
{
if(i==ipoint-2) //插入后位于第ipoint位
{
pBack->next=pNew;
pNew->next=pFront;
return;
}
pBack=pFront;
pFront=pFront->next;
}
pBack->next=pNew;
pNew->next=NULL;
n++;
}
int main()
{
printf("please input student's name and age:\n");
struct student *pHead; //链表头指针
pHead=create(); //创建节点
print(pHead); //输出所有节点
printf("n=%d\n",n);
int ilndex;
printf("please input the node that you want to delete:\n");
scanf("%d",&ilndex);
del(pHead,ilndex); //删除名为cc的节点
printf("After delete:\n");
print(pHead);
printf("n=%d\n",n);
int ipoint;
printf("please input the point that you want to insert:\n");
scanf("%d",&ipoint);
insert(pHead,ipoint); //在名为dd的节点前插入一个节点
printf("After insert:\n");
print(pHead);
printf("n=%d\n",n);
return 0;
}