链表(一)

链表(一)

链表与数组区别

  • 数组:
    • 在逻辑上连续,在物理上也是连续的,需要连续的内存空间,所以如果我们申请一个100MB大小数组,内存空间中没有足够连续空间,即使可用空间大于100MB也会申请失败
    • 具有随机访问特性,可以根据首地址和下标通过寻址公式,就可以直接计算出对应的内存地址,所以查询比较快
    • 数组简单易用,在实现上使用的是连续的内存空间,可以借助CPU的缓存机制,预读数组中的数据,所以访问效率更高
    • 因为在物理上需要保持连续,插入或删除的时候需要整体移动操作位置之后的数据,所以增删比较慢
    • 数组大小固定,申请之后大小就固定了。申请过大过小都不太合理
  • 链表:
    • 在逻辑上连续,但是在物理上可以不用连续。在链表上存在指针域,存储着下一个或上一个结点位置
    • 不具备随机访问特性。只能循环遍历来得到每个数据,所以相比数组查询较慢
    • 链表在内存中并不是连续存储,所以对CPU缓存不友好,没办法有效预读
    • 因为在物理上可以不连续,当增加或者删除的时候只需要改变操作位置的前后指针指向即可,所以相比数组增删快
    • 链表没有大小限制,可以天然支持动态扩容
    • 链表因为需要存储指向下一个或上一个结点的指针,所以存储比数组要浪费内存,如果对链表频繁进行插入删除,就会导致频繁的内存申请、释放,容易造成内存碎片,可能会导致频繁的GC

链表的分类

链表分为:单向链表、循环链表、双向链表

单向链表

链表就是通过指针将一个个不连续的内存块串联起来,形成在逻辑上连续。内存快成为结点,每个节点中都包含两部分,一部分是数据域:用来存放数据,另外一部分是指针域:用来存放指针,指向上一个或下一个结点。

在单向链表中结点的指针域只指向后一个结点,称为后继指针(next)。其中位于第一个结点的是头结点,记录了该链表的基地址,可以通过这个地址找到该链表,最后一个结点成为尾结点,尾结点的指针指向空地址,表明这是最后一个结点。

循环链表

循环链表就是稍微复杂点的单向链表,将单向链表中尾结点的指针,指向头结点,就构成一个循环链表

循环链表的优点就是:从链尾到链头比较方便,在处理数据结构具有环形数据结构的时候,就适合循环链表

双向链表

双向链表与单向链表相比,除了提供指向下一个结点的指针外,还有指向上一个结点的指针,成为前驱结点(prev),在找前驱结点或是插入、删除操作时,比单向链表更加灵活便利

但也有缺点:

  • 因为每个结点需要存储两个指针,所以双向链表要比单向链表耗费更多存储空间,有点类似拿空间换时间的感觉
  • 在删除、更新时,需要操作的指针有四个,比单向链表的多两个

在单项链表删除操作时,若删除某个给定结点,需要获取删除结点前的结点,如果是单向链表,则需要通过遍历来逐一比较来找到前驱结点,时间负责度为O(n),而双向链表可以直接获取前驱结点,时间负责度为O(1);在链表中某个指定结点的前面插入一个结点也是一样的道理。

对于一个有序链表,双向链表的按值查询的效率也要比单链表高一些。因为,我们可以记录上次查找的位置 p,每次查询时,根据要查找的值与 p 的大小关系,决定是往前还是往后查找,所以平均只需要查找一半的数据。

Java实现

LinkedHashMap的实现原理,就用到了双向链表这种数据结构

双向链表体现空间换时间思想,其他例子如:计算机缓存技术,将数据存储到硬盘上,虽然节省内存,但是读取的速度比较慢,如果将数据加载到缓存中,虽然比较占用内存空间,但是读取速度相对较快

基于链表实现LRU缓存淘汰算法

维护一个有序单向链表,越靠近尾部的结点,是越早之前访问的数据。当有一个新的数据被访问时,从链表头部开始顺序遍历链表:

  1. 如果此数据已经被缓存在链表中,在遍历到该结点时,将其从原来位置删除,然后插入到链表的头部。
  2. 如果此数据没有在缓存链表中,又分为两种情况:
    • 此时缓存未满,则将该结点直接插入到链表头部;
    • 此时缓存已满,则将链表尾结点删除,将新的数据结点插入到链表头部;

此时查询缓存时,都需要从头开始便利链表,所以时间复杂度为O(n),可以借助散列表记录每个数据的位置,将时间复杂度降到O(1)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值