数据结构-链表

本文介绍了链表作为一种非连续存储结构,与数组的主要区别以及链表的基本操作,包括插入、删除、遍历。强调了链表操作中的一个原则——画图,两个考点——指针修改和链表拼接,以及三个注意点——环、边界和递归解法。同时,文章通过实例详细解释了链表反转的实现方法。
摘要由CSDN通过智能技术生成

前言

想要刷链表的算法,那必定得先知道它是什么,它的基本操作。

简介

各种数据结构,不管是队列,栈等线性数据结构还是树,图的等非线性数据结构,从根本上底层都是数组和链表。不管你用的是数组还是链表,用的都是计算机内存,物理内存是一个个大小相同的内存单元构成的。而数组和链表虽然用的都是物理内存,都是两者在对物理的使用上是非常不一样的,如图:

在这里插入图片描述
不难看出,数组和链表只是使用物理内存的两种方式。
数组是连续的内存空间,通常每一个单位的大小也是固定的,因此可以按下标随机访问。而链表则不一定连续,因此其查找只能依靠别的方式,一般我们是通过一个叫 next 指针来遍历查找。链表其实就是一个结构体。 比如一个可能的单链表的定义可以是:

interface ListNode<T> {
   
  data: T;
  next: ListNode<T>;
}

data 是数据域,存放数据,next 是一个指向下一个节点的指针。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。从上面的物理结构图可以看出数组是一块连续的空间,数组的每一项都是紧密相连的,所以适合适合查找,而链表由于元素的增删不会影响到整个链表结构,只是将前后元素的指针方向进行改变,因此更适合增删。

链表的基本操作

要想写出链表的题目, 熟悉链表的各种基本操作和复杂度是必须的。

插入

插入只需要考虑要插入位置前驱节点和后继节点即可,其他节点不受影响,因此在给定指针的情况下插入的操作时间复杂度为O(1)。
伪代码:

temp = 待插入位置的前驱节点.next
待插入位置的前驱节点.next = 待插入指针
待插入指针.next = temp

如果没有给定指针,我们需要先遍历找到节点,因此最坏情况下时间复杂度为 O(N)。

删除

如果没有给定指针,我们需要先遍历找到节点,因此最坏情况下时间复杂度为 O(N)。
伪代码:

待删除位置的前驱节点.next = 待删除位置的前驱节点.next.next

遍历

伪代码:

当前指针 = 头指针
while 当前节点不为空 {
print(当前节点)
当前指针 = 当前指针.next
}

链表和数组到底有多大的差异?

说到底,对于我们做题来说,二者的差异通常就只是细微的操作差异。
数组的遍历:

for(int i = 0; i < arr.size();i++) {
   
    print(arr[i])
}

链表的遍历:

for (ListNode cur = head; cur != null; cur 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值