java源码系列:链表是什么?数组和它有何不同?(2022-07-28更新完毕)

目录

一、链表的概念

二、举例解释说明:数组、链表

1、数组

2、链表

三、如何表示链表

1、介绍链表的节点

2、java如何表示链表

四、链表为什么查找比较慢、删除插入比较快?

1、链表为什么查找比较慢?

2、链表为什么删除插入比较快

(1)链表的插入详解

(2)链表的删除详解


一、链表的概念

好了,现在大家已经对咱们这个数组,有一定的了解。详细可参见最近系列文章:

java源码系列:技术的本质?数组到底是什么?数组为何查询快插入慢?_爱折腾的华哥的博客-CSDN博客_数组插入为什么慢

java源码系列:ArrayList的底层实现原理和特性_爱折腾的华哥的博客-CSDN博客

那我想问一下,那为什么,为什么在我们这个 HashMap里面,

既然已经有数组了,为什么还要链表呢?

大家来思考一下,因为我们讲过,我们这个数据结构是用来存储数据的,

那既然我们的数组,都已经可以存储数据了,为什么还要有链表呢?


那这里呢,首先,我们去了解一下链表它的定义,它是这样定义的,

链表是一种物理存储单元,非连续非顺序的存储结构

那刚好跟咱们这个数组是不是相反,你看我们数组它是一个连续的存储单元

而咱们这个链表它是非连续非顺序的。

链表(Linked list)是一种常见的基础数据结构,是一种线性表,

但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

链表可分为单向链表和双向链表。

一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。

一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。

 Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。

二、举例解释说明:数组、链表

那这个怎么去理解呢?

1、数组

我经常举这样一个例子,比如像我们有100兆这样的一个MP4电影视频,

如果是说我们以数组的方式去存储的话,那如果说我们存在D盘上,

那我们这个D盘呢,必须它的容量是有100兆,要不他就存不下。

2、链表

那如果说我们用这种链表的形式呢?

它就可以不用100兆,哪怕你这个D盘只有50兆,另外50兆呢,它可以存在C盘啊。

那这个链表他就是不需要连续的,但是呢咱们这个数组呢,它必须是连续的。

也就是说你这两个必须挨着。

那这就是链表和数组,他们在定义上就有这样的一个区别。

三、如何表示链表

1、介绍链表的节点

链表的每一个元素,你可以看作为一个节点,

节点包括:data域 和 next域

data域:即为存放数据的域。   next域:就是指向它的下一个节点

2、java如何表示链表

好,那我们来看一下链表在我们 java 中怎么去表示呢?

就是当前我创建的这个类,这个类呢,它有一个当前这个data数据,

但是这个类还有一个属性叫next,而它的这个类型,也是当前我这个类的属性,

那也就是这个next,我们叫做什么?

叫做指针,当然我们的这个Java里面叫引用,我们的这个C和C++里面叫指针。

来,咱们现在在这里呢,给大家来说一下,

咱们链表的一个代表形式,是这样的,就是我这张图,

用我们的代码是怎么去表示呢?

看下图,你看我当前的这个 head 节点,我定义为monkey,

然后呢,我这个head 的 next我指向为张三,然后我这个张三的next,我指向为刘一。

所以在这里呢,我们就可以输出monkey、张三、刘一,这三个节点的数据,

 

那这三个节点,在这里,其实它就是 next 的一个指针。

在链表的形式,它是这样的,当前这个monkey呢,叫做链表的头节点

然后呢,指向张三,张三再指向 next 刘一,所以刘一,这就是我们的

四、链表为什么查找比较慢、删除插入比较快?

好,那我们知道链表呢,他的删除插入,时间复杂度为O(1),

在查找遍历的时候呢,它的时间复杂度呢为O(n),

所以呢,我们的链表,它的这个删除插入会比较快,查询比较慢

那我们也可以发现,咱们这个数组它的这个优缺点,刚好跟我们链表的优缺点刚好是相反的。

我们的数组,它是这个删除插入比较慢,但是它的查找比较快

而咱们这个链表呢,刚好就是查找比较慢,但是它的删除插入比较快

那为什么是这样一个情况呢?下面我们来看一下

1、链表为什么查找比较慢?

那大家来思考一下,为什么他的查询比较慢呢?

链表它有一个不好的点,就是它所有的查询呢,首先需要从这个头节点开始

因为它没有元素的下标,也就是需要从这个monkey开始,那如果我这个链表长度又比较长,

然后呢,我们要去找的这个数据又是最后一个数据,

那我们首先先要去查monkey,再去查张三,然后再去查刘一,

举个例子,比如说我们现在去查刘一,那如果要查刘一的话,

首先刘一呢,要跟monkey进行对比,然后再去发现monkey跟刘一不相等,

然后再去找到next的张三,张三再next找到刘一,也就是说我们找刘一的话,我们只需要查什么?

查3次,而我们这个列表的长度才多少,才3个吧!

所以我们可以发现,这就是他查询不利的一个地方。

2、链表为什么删除插入比较快

(1)链表的插入详解

因为链表不需要费时间去移动元素下标。

这又是为啥呢?因为链表不是顺序存储的。

我现在一堆链之间要插一个链进去,我是不是把链解开,

再插一个进去就可以了?对不对?

好,我们来看一下链表的节点,怎么插入,现在这个链表有1、2、3,

有3个节点,那我来了一个4,如下图:

我想把4插到1和2中间,这个4节点我们叫做p,当前1的这个节点叫做curNode,

那我怎么把它插到这个curNode的后边呢?

两件事,第一件事先干啥,注意两步,这个顺序不能反。

如果你说先把1跟4连起来,那对不起,你说错了。

你想一下,如果说你把1跟4先连起来,会怎么样?

1跟4连起来,那么1和2的这个箭头是不是没有了,也就是1它的next是不是指向4了,

那这个2它就找不着了。也就是说没有指向2的东西了,它就游失在内存里了,

一会就被销毁了。

所以第一步不要先把 1 跟 4 它俩连起来。那怎么办?

先把4跟2连起来,所以第一步是什么?  这句话 p.next 等于curNode.next

p.next = curNode.next

把4跟2连起来了,这个时候4指向2

第二步再把1跟4连起来,curNode.next等于p,

p.next = curNode.next

curNode.next = p

这个时候 1指向4,最终 1指向 4,4指向2 ,如下图:

然后这个就是一个新的链表了,这是它的插入。

好,我们看这个的插入,是不是没有任何元素移动,

它是不是就这两句话,两句话都是一个赋值,所以它的复杂度是不是很低啊,它是很快的,

不会像数组一样插入那么慢,对不对?

(2)链表的删除详解

好,这是插入,那同样的我们来看删除。在链表里做删除,怎么删呢?

现在是之前插入之后的那个链表:1、4、2、3,我在想把4删掉,它是p,也就是我想把p删掉,

 第一句话就是想把curNode后边那个节点删掉,

也就是 p等于curNode.next 想把它删掉好,怎么办?

p = curNode.next

 是不是先把1和2俩连起来,4删了之后,4的前面跟他的后边是不是要连起来,

不然的话,4删了,这个2又找不着了。因为你直接把4删掉,

4指向2的这个箭头就没有了,那是不是2就找不着了,所以先把1和2它俩连起来,怎么连?

curNode.next等于p.next或者你只写curNode.next.next也行,也可以再写p.next,

curNode.next = p.next 或者 curNode.next.next

是不是1跟2连起来。然后是不是再把p删掉,

del p

所以这个时候你写一个del p或者不写,都无所谓了,4就是你不要它了,就直接没有了。

那我们这个链表是不是1直接到2到3了,4是不是链过来不管了,所以这个链表就完成了,

这个是删除操作,那同样这个操作,是不是也是一个特别快的操作。

它不像数组,需要移动其他元素的下标,所以它的时间复杂度也是很低的。

参考连接:

Java LinkedList | 菜鸟教程

59 链表的插入和删除_哔哩哔哩_bilibili

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

被开发耽误的大厨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值