Leetcode数据结构&算法:链表

一、简介

 链表分为单链表和双链表

单链表:

单链表中的每个结点不仅包含值,还包含链接到下一个结点的引用字段

 双链表:

双链表以类似单链表的方式工作,与之相比额外还有一个引用字段,称为prev字段。有了这个额外的字段,能够知道当前结点的前一个结点。

链表的特点:

  1. 我们不能在常量级的时间内访问随机位置
  2. 我们必须从头部遍历才能得到我们想要的第一个结点。
  3. 在最坏的情况下,时间复杂度将是 O(N),其中 N 是链表的长度。

 二、单链表的添加和删除操作

1、添加

使用给定值初始化新结点 cur

将 cur的“next”字段链接到 prev 的下一个结点 next

 

将 prev 中的“next”字段链接到 cur

与数组不同,我们不需要将所有元素移动到插入元素之后。因此,您可以在 O(1) 时间复杂度中将新结点插入到链表中,这非常高效。

 在链表添加新新节点有锁不同:

在开头添加新节点时更新头结点 head 至关重要。

  1. 初始化一个新结点 cur
  2. 将新结点链接到我们的原始头结点 head
  3. 将 cur指定为 head。 

2、删除

想从单链表中删除现有结点 cur,可以分两步完成:

(1)找到 cur 的上一个结点 prev 及其下一个结点 next

(2)接下来链接 prev 到 cur 的下一个节点 next

在我们的第一步中,我们需要找出 prev 和 next

使用 cur的参考字段很容易找出 next;但是,我们必须从头结点遍历链表,以找出 prev ,它的平均时间是 O(N),其中 N 是链表的长度。因此,删除结点的时间复杂度将是 O(N)

空间复杂度为 O(1),因为我们只需要常量空间来存储指针

三、双链表的添加和删除

1、添加

如果我们想在现有的结点 prev 之后插入一个新的结点 cur,我们可以将此过程分为两个步骤:

(1)链接 curprev next,其中 nextprev 原始的下一个节点;

(2)用 cur重新链接 prev next

与单链表类似,添加操作的时间和空间复杂度都是 O(1)

2、删除

想从双链表中删除一个现有的结点 cur,我们可以简单地将它的前一个结点 prev 与下一个结点 next链接起来。

与单链表不同,使用“prev”字段可以很容易地在常量时间内获得前一个结点。

因为我们不再需要遍历链表来获取前一个结点,所以时间和空间复杂度都是O(1)

 四、总结

让我们简要回顾一下单链表和双链表的表现。

它们在许多操作中是相似的。

  1. 它们都无法在常量时间内随机访问数据
  2. 它们都能够在 O(1) 时间内在给定结点之后或列表开头添加一个新结点
  3. 它们都能够在 O(1) 时间内删除第一个结点

但是删除给定结点(包括最后一个结点)时略有不同。

  • 在单链表中,它无法获取给定结点的前一个结点,因此在删除给定结点之前我们必须花费 O(N) 时间来找出前一结点。
  • 在双链表中,这会更容易,因为我们可以使用“prev”引用字段获取前一个结点。因此我们可以在 O(1) 时间内删除给定结点。

这里我们提供链表和其他数据结构(包括数组,队列和栈)之间时间复杂度的比较:

经过这次比较,我们不难得出结论:

如果你需要经常添加或删除结点,链表可能是一个不错的选择。

如果你需要经常按索引访问元素,数组可能是比链表更好的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值