C语言学习心得日记——链表及链表的使用

对于链表肯定很多人都听过,但什么是链表估计大部分非科班出生的人都没有系统的学过,但链表确实是一种很重要的东西,让我们一起来剖析链表究竟是何方神圣。

一、什么是链表?
链表是一种很重要的数据结构,我们可以从它的作用上简单的理解为链表和数组一样,是一串类型相同的数据。用来存放一组数据。
有的人可能就会问,不是已经有数组能够实现存放一组数据的功能了吗?为什么要要用链表呢?这就得从数组和链表的区别来看了。

1)数组
数组是一串地址连续的空间,空间连续的好处是遍历起来比较简单,直接写个for循环++就好了。但世界上每件事都有两面性。
如果想在数组的头部插上或删除一个数据,就得把数据全部后移一位,如果在数据量很大的情况下,实现此工能的效率将会很低。
除此之外,数组是静态的空间,不能做动态扩展,也就是说在数组创建之初,数组的大小就确定了,如果小了就不够用,大了则会造成资源的浪费。
基于数组的这两点缺陷,链表出现了。

2)链表
链表由一个个的节点组成,节点则由数据域和指针域两部分组成,如下图:

在这里插入图片描述
数据域用来存放数据。
指针域则用来存放下一个节点的地址。如下图所示:

在这里插入图片描述
每个节点的指针域都存放了下一个节点的地址,所以节点之间的地址不一定是连续的,能够更有效的使用内存空间.。如果想进行头部插入,则只需将将新创节点的指针域指向原先第一个节点的地址即可。

二、链表的分类
链表可以简单的分为静态链表和动态链表。静态链表即栈上的链表,动态链表则为堆上的链表。
此外,也可以分为单向链表)、双向链表、单向循环链表、双向循环链表

三、带头的链表
所谓的带头链表就是固定一个节点,只使用其指针域用于存放第一个有效数据节点的地址的链表。这个节点起到一个索引的作用,通过它就可以对整个链表的数据进行处理,在链表遍历和出入删除数据时大有作用。

三、链表的实现和使用
1)链表的实现
链表是由节点构成的,我们要创建一个链表,首先得先创建节点。
根据节点由数据域和指针域构成的特性,节点可以用结构体来实现,即:
struct ListNode
{
int num;//定义存放的数据类型,相当于数据域,这里以int为例
struct ListNode *next;//定义节点指针,存放下一个节点的地址,相当于指针域
}
定义好节点后就可以创建并初始化节点了,如:
struct ListNode p1={1,NULL};//这里指针域先指向空,等下节点之间建立联系再指向其他节点的地址
struct ListNode p2={2,NULL};
struct ListNode p3={3,NULL};
struct ListNode p4={4,NULL};
struct ListNode p5={5,NULL};
这里我们创建了5个节点,现在这5个节点都是独立的,接下来,我们要将这些节点建立联系,即p1的指针域指向p2的地址,p2的指针域指向p3的地址…最后p5的指针域指向空(如果是循环链表,则p5的指针域指向p1的地址),如下所示:
p1->next=&p2;
p2->next=&p3;
p3->next=&p4;
p4->next=&p5;
p5->next=NULL;
节点之间的联系建立好后,链表就已经定义完成了

2)遍历链表
链表建立好后,最重要的就是对链表进行操作了,我们生活中也是,做某件物品出来的目的就是去用它。
遍历链表是最常规的操作,那么,链表要怎么遍历呢?它的地址是不连续的,不像数组一样写个for循环++就好了,对于链表的遍历我们要用到指针域。
//先定义一个指针,指向链表第一个节点的地址:
struct ListNode*hp=&p1;
//如果下一个节点的指针域不为NULL,则将hp指向第二个节点,再进行判断,直到指针域为空则退出循环
while(hp->next!=NULL)
{
printf("%d\n",hp->num)//打印数据域中的值;
hp=hp->next;//将指针hp指向下一个节点的位置
)
当hp指向第5个节点时,hp->next=NULL,退出循环,遍历结束。

3)插入和删除数据
现在我们创建的链表数据域为1、2、3、4、5。
对于插入数据,可以分为尾插、中部插和头插三种方式,如下:
①我们如果想在5后面插入一个数据,直接定义一个节点p6,p5的指针域指向p6的地址就好了。

②如果要在2和3之间插入一个数据,则只用改变p2的指针域,同样先创建一个节点p2.5,将p2的指针域指向p2.5的地址,p2.5的指针域指向p3的地址就好了。

③如果要在1前面插入一个数据,则以同样的方式先创建一个节点p0,将p0的指针域指向p1的地址。但这种方式有一个缺点,那就是第一个节点的地址会一直在变(变成每次新创建节点的地址),为了防止这种情况,我们一般在创建链表的时候都是创建带头链表,即定义一个头节点struct ListNode headp;头节点的数据域存放的是无效数据,我们只使用它的指针域,其指针域指向第一个节点的地址。我们要在1前插入一个数据,则只要将创建好的p0的指针域指向p1的地址,再将头节点headp的指针域指向p0的地址就好了,这样无论在头部插入几个数据,头节点的地址依旧是不变的。

对于删除数据,本质上其实也是对节点的指针域进行操作,如果要删除3这个数据,则只需从逻辑上删除,将p2的指针域指向p4的地址就好了。
如果创建的是动态节点,则在改变指针域后将p3free掉就ok了。

4)清空链表
所谓的请空链表,就是将链表存放的数据清除掉,相当于把一个袋子的垃圾都丢了,但这个袋子还可以继续拿来装垃圾。
我们只需将除了头节点以外的节点都free掉,再将头节点的指针域指向NULL就可以了。

5)消除链表
消除和清空的差别是链表还能不能再使用,消除相当于你把垃圾袋连同垃圾一起丢了,想再用这个垃圾袋就不可能了。我们只需把头节点和其他节点一起free掉就可以了。

6)总结:
链表的操作还有很多,但大多都是基于以上这些知识点来进行的,以后遇到了我在发出来。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值