单链表专题

一.链表的概念和结构:

     顺序表是线性表的一种,链表也是,顺序表其物理结构是不一定连续的,而其逻辑结构是连续的。而链表在物理结构上一定不是连续的,逻辑结构是连续的。

     概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

   我们可以将链表抽象成一节节火车,每节火车连着下一节火车,能从上一个火车找到下一个火车。每节车厢都是独立存在互不干扰,链表也是如此,独立存在互不干扰。

   在链表中数据是怎么存放,并且怎么找到下一个车厢里存放的内容的:

    

在链表中存放着两个内容:一个是存放的数据,一个是下一个节点的地址,这样就可以找到下一个节点存放的内容。

     了解了链表的基础内容,接下来就是如何用代码实现链表:

二.单链表的实现:

     想要实现单链表,首先要分析这个单链表里面有什么,怎么串联起来建立连续的关系。根据图解可以看出链表里面存着数据,和指向下一节点的指针。

     了解之后就可以定义链表的节点结构:

1.定义节点结构:

     

当我们想要保存⼀个整型数据时,实际是向操作系统申请了⼀块内存,这个内存不仅要保存整型数
据,也需要保存下⼀个节点的地址(当下⼀个节点为空时保存的地址为空)。
当我们想要从第⼀个节点⾛到最后⼀个节点时,只需要在前⼀个节点拿上下⼀个节点的地址即可。

2.链表的打印:

   定义完节点结构后,来实现链表的打印,方便后续功能实现能够直观看出结果是否正确。

  想要打印就得先创建几个节点:

在这里创建了四个节点,并且存放了数据进去,但是这还不是链表,还要将这几个节点连接起来:

链表打印函数的实现:

当走出循环时就是空指针了。

现在来测试一下打印结果:

但我们之后要实现链表的各种功能,我们这样创建节点就会很麻烦,所以我们现在来构造一个函数用来创造节点。

2.节点的创建:

这样我们就可以直接调用函数来创建节点了,就不需要自己创建节点了。让程序更加方便。

3.链表的尾插:

首先plist存放着链表的首节点的地址,是一个一级指针,在这里我们想要尾插数据,也就是先让尾节点的地址指向新插入的数据的地址,而在函数中想要改变其内容并且传回去时,就要用到指针,这里是一级指针,所以我们就要用到二级指针。

所以在这里我们就知道了函数的参数,一个是二级指针,一个是要插入到节点中的数据。

在这里用到了二级指针,所以接下来就要知道二级指针每次解引用的含义是什么:

这幅图十分重要,后面写代码就会频繁使用,这幅图也便于理解。

在这里尾插就有两种情况了

第一种:就是链表中是空,没有数据:

第二种:就是链表不为空,这样就要遍历整个链表,来寻找尾节点:

当循环走到这一步时就会停止循环,此时再将新的节点与上面节点的末尾连在一起。

尾插的整个代码如图:

接下来测试一下尾插是否成功:

如图尾插成功。

4.链表的头插:

     头插就十分简单了,不管是不是空链表,直接把要插入的节点变成第一个节点即可。

这两步的顺序不能调换,如果调换则一开始的第一个节点的位置找不到了,无法串联在一起了。

接下来测试一下头插:

如图头插成功。

5.链表的尾删:

尾删也有两种情况:

第一种情况:

就是尾部只有一个节点,此时要做的就是释放掉这个节点,并将节点的指向空,不让其变为野指针。

当第一个节点指向的下一个位置是空指针则代表这个链表只有一个节点所以可以这样判断:

第二种情况:

不止一个节点,此时就要遍历整个链表来找尾,如图来进行找尾:

此时不能只有一个指针来记录位置,如果只用一个ptail的话当释放掉这个尾节点后就找不到了,并且无法将尾节点指向空指针,会导致变成野指针。

这时再创建一个指针来记录尾节点的地址。

图解完成后,下面是代码:

整个尾删的代码如图:

接下来测试尾删:

如图尾删成功。

6.链表的头删:

头删就比较简单了,直接利用一个指针记录第一个节点指向下一个节点的地址,然后再将第一个节点释放掉即可。

这就是头删代码,现在来测试一下是否正确:

如图,头删成功。

7.链表的查找:

查找就是遍历整个链表,找到那个数据所在节点的位置。

再创建一个指针,当循环进行到如图时,循环就停止,就代表没有找到,就返回空指针。所以循环条件就是pcur->next ! = NULL

如图代码完成,现在来测试一下:

如图测试成功。

8.在链表指定位置之前插入数据:

首先利用链表查找函数找到要那个指定位置,再利用节点的创建函数,创建一个节点。

这里也有两种情况:

情况一:指定位置为第一个节点,则就是在第一个节点前插入一个节点,此时就是链表的头插,

这时只需要将要插入的数据头插到链表中即可:

情况二:指定位置不为第一个节点:

假设指定位置在这,首先再定义一个指针用来遍历链表找到指定位置:

此时遍历循环条件就是prev->next != pos,当prev->next ! = pos时就不断往下走,当其到达指定位置后循环停止:

此时循环结束,如图:

此时只需要将newnode->next指向pos,再将prev->next=newnode.

此时代码完成 现在来测试一下:

在1前面正好插入了3,所以代码正确。

9.在链表指定位置之后插入数据:

按照这个图解写出的代码是有错误的,因为这样newnode->next就找不到了,所以没办法将其连接起来。

这才是正确的步骤,这样就可以将整个链表顺利连接起来。

写完之后来测试一下:

如图,插入成功。

10.删除指定节点:

还是有两种情况:

情况一:就是指定节点为头节点时:

这时直接调用封装好的链表的头删的函数:

情况二:删除的指定节点不是头节点:

此时利用一个指针来遍历链表找到指定的位置。

根据图解可以写出代码:

整体代码:

现在来测试一下:

如图测试成功

11.删除指点位置后的节点:

如果写成这样:

这个就有错误了,如果是空链表的话,就不能对空指针解引用。

如果直接利用pos->next->next的话,如果是删除最后一个节点后的位置,则对空指针解引用就会出错

代码写完了,接下来来测试一下:

运行正确。

12.销毁链表:

想要销毁链表,就要遍历整个链表一个个销毁每个节点:

当销毁第一个节点时,需要另一个指针来记住下一个节点的地址,不然销毁了一个就找不到了

整个代码如图,接下来测试一下:

销毁成功。

三.总结:

综上关于单链表的实现就这样完成了,其实整个过程还是有很多细节需要注意的。今天的博客到这里就结束了,谢谢观看。

 

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值