数据结构与算法-链表(一)简介


看一下基本的数据结构
在这里插入图片描述

链表

相比数组,链表是一种稍微复杂一点的数据结构。从底层的存储结构上来看:数组需要一块儿连续的内存空间,堆内存的要求比较高,如果我们申请一个100MB大小的数组,当内存中没有连续的、足够大的空间的时候,即便内存的剩余总可用空间大于100MB,仍然会申请失败;而链表恰恰相反,它并不需要一块儿连续的内存空间,它通过“指针”将一组零散的内存块串联起来,所以如果我们申请100MB大小的链表,如果没有100MB连续的内存空间,且内存的剩余总可用空间大于100MB,根本不会有问题;

链表实际上是线性表的链式存储结构,与数组不同的是,它是用一组任意的存储单元来存储线性表中的数据,存储单元不一定是连续的,且链表的长度不是固定的,链表数据的这一特点使其可以非常的方便地实现节点的插入和删除操作。
链表的每个元素称为一个节点,每个节点都可以存储在内存中的不同的位置,为了表示每个元素与后继元素的逻辑关系,以便构成“一个节点链着一个节点”的链式存储结构,除了存储元素本身的信息外,还要存储其直接后继信息,因此,每个节点都包含两个部分,第一部分称为链表的数据区域,用于存储元素本身的数据信息,这里用data表示,它不局限于一个成员数据,也可是多个成员数据,第二部分是一个结构体指针,称为链表的指针域,用于存储其直接后继的节点信息,这里用next表示,next的值实际上就是下一个节点的地址,当前节点为末节点时,next的值设为空指针

当你拿到第一个元素就已经把整条链表给你了。

常见的链表:单链表;双向链表;循环链表

一、单链表

链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块成为链表的“节点”。为了将所有的节点穿起来,每个节点除了存储数据以外,还需要记录链上的下一个节点的地址,我们把这个记录下个节点地址的指针叫做后继节点 next

在这里插入图片描述

链表的增删改查

我们在进行数组的插入、删除操作的时候,为了保持内存数据的连续性,需要进行大量的数据搬移工作,所以时间复杂度为 O(n);而在链表中插入或者删除一个数据我们并不需要为了保持内存的连续性而搬移节点,因为链表本身的存储空间也不是连续的,所以在链表中插入和删除一个数据是非常快的;

插入数据: 我们只需要将要插入位置的前一个数据单元的next指针指向插入数据的内存地址,插入数据的next指针指向下一个数据的内存地址;

删除数据: 将要删除数据的前一个数据单元的next指针指向要删除数据的下一个数据单元的内存地址,然后再删除数据;
在这里插入图片描述
但是,链表想要访问第k个元素时,就没有数组那么高效了。因为链表中的数据并非连续存储的,所以无法像数组那样根据首地址和下标,通过寻址公式就能计算出对应的内存空间,而是需要根据指针一个节点一个节点的依次遍历,直到找到相应的节点。

链表就好比是在学校站队一样,假如我们都只知道自己后面的人是谁,如果我们想知道第k个人是谁,我们就需要从第一个人开始,一个一个的往下数。所以,链表随机访问的性能没有数组好,需要O(n)的时间复杂度;

二、循环链表

循环链表其实就是一种特殊的单链表,它根单链表唯一的区别就在于尾节点,上文我们提到单链表的尾节点的next指针指向空地址,表示这是最后的节点了;而循环链表的尾节点指针指向的是链表的头结点,如下图,它就像一个环一样收尾项链,所以叫做循环链表
在这里插入图片描述
和单链表相比,循环链表的优点是从链尾到连头比较方便,当要处理的数据具有环形特点时,就特别适合使用循环链表。

三、双向链表

单链表只有一个方向,节点只有一个后继指针next指向后面的节点。而双向链表支持两个方向,每个节点不仅有一个后继指针,还有一个前驱指针prev指向前面的节点。
在这里插入图片描述
空间换时间的设计思想。当内存空间充足的时候,如果我们更加追求代码的执行速度,我们就可以选择空间复杂度相对较高、但时间复杂度相对很低的算法或者数据结构。相反,如果内存比较紧缺,比如代码跑在手机或者单片机上,这个时候,就要反过来用时间换空间的设计思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值