数据结构——链表

本文介绍了链表作为数据结构的一种,对比了链表与数组的区别,强调了链表在内存管理和操作上的灵活性。讨论了单链表、循环链表和双向链表的特性,并分析了它们在插入、删除操作上的时间复杂度。同时,文章提供了编写链表代码的技巧,包括理解指针、避免内存泄漏、利用哨兵节点以及处理边界条件的重要性。
摘要由CSDN通过智能技术生成

链表也是一种数据结构,相比较于数组,略显复杂。链表和数组都是非常基础、非常常用的数据结构。

1. 数组与链表的区别

从底层的存储结构上看,二者申请的内存空间不一样:

  • 数组需要一块连续的内存空间来存储,对内存要求较高。

  • 链表不需要一块连续的内存空间,它通过"指针"将一组零散的内存块串联起来。

例如,当我们申请一个100MB大小的数组,当内存空间中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于100MB,仍然会申请失败。但如果我们申请的是100MB大小的链表时,就可以申请成功。
对比图如下:
在这里插入图片描述

2. 三种常见的链表结构

链表结构有很多种,但最常见的主要有如下三种:

  1. 单链表

  2. 双向链表

  3. 循环链表

2.1 单链表

链表通过指针将一组零散的内存块串联在一起,我们将内存块称为链表的“结点”。为了将所有的结点串联在一起,每个链表的结点除了要存储数据之外,还需要记录链上的下一个结点的地址,如下图所示,将记录一个结点地址的指针叫作“后继指针next”。
在这里插入图片描述
从上面单链表的图中可以看到有两个结点比较特殊,分别是第一个结点和最后一个结点。我们习惯性的把第一个结点叫作头结点,最后一个结点叫作尾结点。

头结点用来记录链表中的基地址,可以根据头结点遍历得到整个链表。

尾结点的指针不是指向下一个结点,而是指向一个空地址NULL,表示这是链表上最后一个结点。

在链表中进行数据的插入和删除操作要比数组中高效。因为在数组中进行插入、删除操作时,为了保持内存数据的连续性,需要做大量的数据移动,时间复杂度是O(n)。而在链表中存储空间本身就不是连续的,不需要为了保持内存的连续性而移动大量的数据。

为了方便理解,看一张链表中数据插入和删除操作的图:
在这里插入图片描述
从图中可以看出,在链表的插入和删除操作中,我们只需要考虑相邻结点的指针改变,所以对应的时间复杂度是O(1)。

链表中数据的插入和删除比数组高效,但当需要随机访问第k个数据时,就没有数组高效。因为链表中的数据不是连续存储的,无法像数组那样,根据首地址和下标,通过寻址公式直接计算出对应的内存地址,而是需要根据指针一个结点一个结点依次遍历,直到找到对应的结点。

2.2 循环链表

循环链表的本质是一种特殊的单链表,与单链表的区别就是在尾结点。单链表中的尾结点指针指向空地址,表示这就是最后的结点。而循环链表的尾结点指针指向链表的头结点。
在这里插入图片描述
从上面的图中可以看出循环链表像一个环一样首尾相连,因此称作“循环”链表。

与单链表相比,循环链表的优点是从链尾到链头比较方便。当需要处理的数据具有环形结构特点时࿰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值