(C语言)链表详解 附带代码演示(通俗易懂)

数组和链表都可以存放数据,数组的格式如下

int a[3] = {1,2,3};
a[3]data
a[0]1
a[1]2
a[2]3
然而对于数组来说,删除数组中指定为位置的元素,插入一个元素显得复杂且麻烦。

人们想出利用一个结构 来使各种操作变得更加方便,这个结构便是链表。

链表各成分理解

1、头文件

头文件需要包含

#include<stdio.h>
#include<stdlib.h>

2、定义结构体

需要包含 数据域 和 指针域
数据域:可以是各种数据类型组合一起
指针域:通过指针来使各节点连接在一起,从而快速实现各种操作
typedef struct student
{
	char name[100];
	int age;
	student *next; //也可以规范一点写成struct student *next 
};

这就是很简单的单链表的一个节点,可以表示为

在做下一步操作之前,先理解两个操作

1、指针访问结构体中的数据。

当定义一个指针指向结构体时,例如:

student stu1={"hjw",18}; //自定义结构体内容
student *p = &stu1;      //指针指向结构体stu1的地址
操作 p->name 或者 p->age 为访问结构体中的数据,若 p->age=19 ,即直接修改了stu1的数据age为19。

代码如下

typedef struct student
{
	char name[100];
	int age;
	student *next; //也可以规范一点写成struct student *next 
}student;


int main(void)
{
	student stu1={"hjw",18};
	student *p = &stu1;
	printf("%s,%d\n",p->name,p->age);
	p->age=19;
	printf("%d\n",p->age);
	return 0; 
}

运行结果:

hjw,18
19

--------------------------------
Process exited after 0.07111 seconds with return value 0
请按任意键继续. . .
2、分配储存空间

要想存入一个数据,则需要利用malloc函数来开辟新的空间。此时你并不知道需要开辟多大的空间。可以直接利用sizeof函数来确定你所需要的空间大小。

注意:使用malloc函数返回的是void*的指针,所以还需要强制转换为你所需要的类型。
若如上文我们所写的一样,需要强制转换成student*的类型,则如下所示
student *p1;
p1 = (student *)malloc(sizeof(student));
表示:指针 p1 指向 结构体student大小的 内存区域

3、创立第二个链表节点,并尝试连接起来

由第二点的操作,我们可以定义 两个指针 指向 两个结构体的内存区域 ,并通过这两个指针来进行 数据的修改等操作

先定义两个指针,并指向两个结构体的内存区域。

	student *p1,*p2;
	p1 = (student *)malloc(sizeof(student));
	p2 = (student *)malloc(sizeof(student));
再通过这两个指针进行数据的填充

由于发现给了下标的数组不好赋值,我们可以利用指针字符串的方式定义名字

把char name[100] 修改为 const char *name
即把结构体改为了

typedef struct student
{
	const char *name;
	int age;
	student *next; //也可以规范一点写成struct student *next 
}student;
进行数据填充:

	p1->name = "hjw";
	p1->age= 18 ;
	p2->name = "wjh";
	p2->age = 81;
	
检测一下是否填充成功	
	printf("%s %d\n",p1->name,p1->age);
	printf("%s %d\n",p2->name,p2->age);


运行结果为
hjw 18
wjh 81

--------------------------------
Process exited after 0.05025 seconds with return value 0
请按任意键继续. . .

此时用图表示为

在这里插入图片描述

再把这两个链表连接在一起

p1->next = p2;

在这里插入图片描述

这就是最简单的链表。

要想做更多操作,则需要把 头链表 以及 尾结点 给记录起来。

student *head;
head = p1;
把头链表 p1 的位置记录给 head 。
p2->next = NULL;
把尾结点给标记为NULL,即进行操作时,可以通过这个终止操作。

表示为:在这里插入图片描述

这便是最简单的链表,此时已经实现了连接的操作了

利用循环语句,实现多链表的连接

直接上源代码:
#include<stdio.h>
#include<stdlib.h>



typedef struct student
{
	const char *name;
	int age;
	student *next; //也可以规范一点写成struct student *next 
}student;


int main(void)
{
	student *p;
	student *head;
	student *p1,*p2;
	head = 0;
	for(int i=0;i<=5;i++)
	{
		p1 = (student *)malloc(sizeof(student));//p1指向开辟一个内存
		p1->age = i;                            //数据的插入
		if(head == 0)                           //用if条件句判断head是否指向头链表
		{
			head = p1;
			p2 = p1;
		}
		else                                   //head已经标记头链表了
		{
			p2->next = p1;            //p2用来标记上一次的内存,把上一个内存的next指向下一个 
			p2 = p1;                  //p2为下次的连接做准备
		}
	}
	p1->next = NULL;
	p = head;                         //p指向头链表,方便操作
	while(p != NULL)
	{
		printf("%d ",p->age);
		p = p->next ;
	}
	return 0; 
}
运行结果:

0 1 2 3 4 5
--------------------------------
Process exited after 0.03945 seconds with return value 0
请按任意键继续. . .

下面开始解释一些常见的链表操作

输入数据并连接链表

输入数据:

	p1 = (student *)malloc(sizeof(student));
	scanf("%s",p1->name);
	scanf("%d",&p1->age)


再设置循环语句,连接链表

	if(head == 0)
	{
		head = p1;
		p2 = p1;
	}
	else
	{
		p2->next = p1;
		p2 = p1;
	}
标记一个变量,使输入数据可以结束循环。

直接上代码:
#include<stdio.h>
#include<stdlib.h>



typedef struct student
{
	char name[20];//改为数组
	int age;
	student *next; //也可以规范一点写成struct student *next 
}student;


int main(void)
{
	student *p;
	student *head;
	student *p1,*p2;
	head = 0;
	char q;
	
	
	
	while(1)
	{
		printf("continue?(y/n)\n");
		scanf("%c",&q);
		
		
		if(q=='y')
		{		
			
			
			p1 = (student *)malloc(sizeof(student));
			
			
			printf("your name:");
			scanf("%s",p1->name);
			printf("age:");
			scanf("%d",&p1->age);
			getchar();

			
			if(head == 0)
			{
				head = p1;
				p2 = p1 ;
			}
			else
			{
				p2->next = p1;
				p2 = p1;
			}
		}
		else
		{
			break;
		}
		

	}
	
	
	p1->next = NULL;
	p = head;
    printf("%s:%d",p->name,p->age);
    p=p->next;
    printf("%s:%d",p->name,p->age);
	return 0; 
}

删除链表

三个节点,第一个节点直接连接到第三个节点上,释放第二个链表的内存。

释放内存的函数为free()。

原理图:

在这里插入图片描述

--------------------------------------------------------------------------------------------------------------------------在这里插入图片描述


在这里插入图片描述

即完成了删除链表的操作。

查找链表(删除特定的链表)

利用while等循环语句,遍历链表直至查到所需要的数据位置。
1.通过学号或者年龄等数据查询
例如通过年龄来查询
int a;
scanf("%d",&a);
while(p->age != a )  //当年龄符合要求时,退出循环
{
	p = p->next;   //p循环一次都会向下移动一个链表
}
怎么查询多个同一年龄的人呢?可以改进为:
int a;
scanf("%d",&a);
while(p->age != a || p != NULL)
{
	if(p->age == a)
	{
		printf("%s:%d",p->name,p->age);
	}
	p = p->next;
}
2.通过数组中的元素查询,例如名字
可以借助关于 字符串 的函数来实现。例如strcmp()

字符串比较函数strcmp的比较,两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。基本形式为strcmp(str1,str2),若str1=str2,则返回零,若str1<str,,则返回负数;若str1>str2,则返回正数。

char a[20];
scanf("%s",a);
while(!strcmp(a,p->name) || p != NULL)
{
	if(!strcmp(a,p->name))
	{
		printf("%s:%d",p->name,p->age);
	}
	p = p->next;
}

还有更多进阶操作,以后更新。新人刚学编程,如有错误可以和我说一下,大家可以帮忙点个赞吗?

  • 24
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值