C语言写链表思路及步骤详解

本人已经大二,大一第一学期就学习了C语言,链表也是那时候就学了。对于学过链表的人来说,觉得很简单;但对于没学过的人来说,觉得概念很难理解。想起以前学习的过程,自学时在网上搜到的讲解,要么只讲代码,要么讲的思路很难理。为了赚积分升二级拿模板,从初学者的角度出发慢慢讲解,请慢慢看。如有大神路过看见有误,还请大神指点一二。

1.重温结构体

我想既然你接触了指针,那就一定学过结构体了。下面定义了一个结构体,typedef代表重命名;struct代表结构体,是一种固定的语法;大括号中的各种类型代表在这个结构体中有那些类型的数据,这个随便定义,定义什么类型、定义多少个都行;XUE代表该结构体重命名的新名字,如果开头没有typedef关键字就不能写。

typedef struct xuesheng			//学生基本信息结构体
{
	char xuehao[3];			//学号 
	char xingming[10];		//姓名 
	int age;						//年龄 
	struct xuesheng *next;	//指针域 
}XUE;

那么这样定义的结果是什么?在思维上理解为,在内存中开辟了一个空间,空间的大小根据定义数据类型的大小而开辟,比如char代表一个字节,但char xuehao[3]就代表3个字节,思维上理解为下图所示,开辟之后就把该整块空间命名为XUE
在这里插入图片描述
可能你会疑惑,struct xuesheng *next是什么意思,有什么作用?struct xuesheng代表一种类型,和char、int一个性质,*next代表指针,连起来就是,struct xuesheng类型的指针,名字为next。具体作用后面第4步再讲,嘻嘻

此时你可能又疑惑了,struct xuesheng类型占多大的空间,不然怎么在内存中开辟固定大小的空间?首先,你得知道指针本质是一个内存地址,里面记录的是某处内存的地址。然后指针也有类型,如int、double、char等。既然是地址,所以她的大小在win32中是4个字节,在win64中就是8个字节。

此时你可能又感到疑惑,指针不是有类型吗?char型不是只占一个字节吗?因为指针的类型并不决定指针的空间大小,只是决定该指针能指向什么类型的变量。C语言是强类型的语言,指针也是一种变量,如果变量没有类型,呵呵。。。

2.malloc函数的详解

假设我想存储班级的信息,学号、姓名、年龄都有了,可是使用静态的方式定义一个结构体的话,就要为每个人定义一个结构体变量,如果班级有一百多号人,那就要定义一百个变量?NO,C语言有动态管理内存的函数malloc,该函数能在内存堆中开辟指定大小的空间。比如,我想开辟上面定义的结构体大小的空间就这么写

(XUE*)malloc(sizeof(XUE))

第一个小括号代表开辟了该块空间之后返回什么类型,(XUE*)代表返回XUE结构体指针类型(之前已经将结构体重命名为XUE了),如果你不想写重命名后的名字,可以这样写(struct xuesheng*),记住一定是返回指针类型,也不能写其它的指针类型,如int *、char *等都是不行的,因为前面已经说过的类型决定该指针能指向什么类型的变量,你想想,你开辟了该结构体类型而返回整型,那样能行吗。
第二个小括号代表开辟空间的大小。sizeof()也是一个函数,该函数用于统计某变量的空间大小,sizeof(XUE)的作用就是统计XUE结构体的大小。

3.创建链表的思维

都知道数组是线性表,在内存中的思维上可以这样理解
在这里插入图片描述
这样寻址很方便,只要指出下标就能找到某个位置,可是缺点也很明显,就是它的大小一开始就要定义好,之后就不能改变了,不够灵活,而且开辟时一定要找一个比它大的空闲空间。
假设一个内存100M大小,运行10个10M大小的app,内存用完,此时5号程序和7号程序都关闭释放了原来占用的内存,此时空闲20M内存,并且两块空间分隔开的,当我想申请一个20M的空间时,如果像数组一样申请是不能够申请的,因为数组要连续的空间,不能分隔开。
在这里插入图片描述
所以链表就诞生了,链表能在5号处申请该块空间,再在7号处申请空间,然后把他们连起来,OK,完事

4.代码实现及讲解

先贴上代码,如果看注释看不懂,可以看后面的讲解

#include<stdio.h>
typedef struct xuesheng			//学生基本信息结构体
{
	char xuehao[3];			//学号 
	char xingming[10];		//姓名 
	int age;				//年龄 
	struct xuesheng *next;	//指针域 
}XUE;
int main()
{
	XUE *head,*yidong,*end;//定义结构体指针
	head=(XUE*)malloc(sizeof(XUE));//使用head指针接收开辟空间后返回的地址
	yidong=head;//将head指针存储的地址赋给yidong指针,即他们都指向开辟空间的地址
	for(i=1;i<=3;i++)//开辟三个节点
	{
		end=(XUE*)malloc(sizeof(XUE));//继续用end指针接收新开辟空间后返回的地址
		printf("请输入学号:"); 
		scanf("%s",end->xuehao);//使用该节点存储数据
		printf("请输入姓名:"); 
		scanf("%s",end->xingming);//使用该节点存储数据
		printf("请输入年龄:"); 
		scanf("%d",end->age);//使用该节点存储数据
		yidong->next=end;//将yidong指向空间中的next变量指向end指针指向的空间
		yidong=end;//yidong指针重新指向end指针指向的空间
	}
		return 0;
}

定义结构体指针就是简单的定义语句,定义了三个指针变量。看名字你应该有一点点想法了,哈哈
head指向开辟空间,如下图。注意是指向了整个空间,而不是指向了某个变量。这一整个空间又称为节点
在这里插入图片描述
yidogn=head之后就如下图,yidong也指向了该节点在这里插入图片描述
开始循环,循环3次,说明我想创建三个节点。
之后end指向开辟的空间,内存的使用如下图
在这里插入图片描述
接着我使用scanf语句向里面输入数据,如下图
在这里插入图片描述
yidong->next=end的效果如下图,next变量指向了end指向的节点。注意,是指针变量,前面挖了一个坑说后面再说,next是struct xuesheng *类型,而节点就是这个类型,所以能够指向别的节点。
在这里插入图片描述
接着yidong=end的效果如下图。为什么能这么容易的寻找到别的节点并赋值?这就是指针的强大,指针指向了该块地址之后就能轻易的寻找和修改该块地址的东西
在这里插入图片描述
此时第一次循环结束,第二次循环结束后如下图
在这里插入图片描述
第三次循环结束后如下图
在这里插入图片描述
注意

  1. 我上面的next中没有写东西并不是代表它没有存储数据,它里面存储的是指向某节点的地址。但是最后一个节点next没有存储东西,因为它后面没有东西可指了。
  2. end每次循环都指向开辟的新节点,而上一个节点由yidong提供,当yidong提供完地址之后,即使yidong->next指向end之后,yidong就指向end的节点。

end

因为有个空的节点,所以上面建的链表又称为带头节点链表
因为指针的方向只有一个,所以又称为单向链表
链表能充分利用内存的空间,灵活开辟空间和使用,但也有一个缺点,就是查找某个节点的时候要从头开始(双向链表除外)
如果觉得对你有用,给个👍

  • 58
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值