集合框架之LinkedList

先来说一下ArrayList和LinkedList的区别的,再梳理一遍,加强记忆和理解。

ArrayList底层使用数组实现,连续内存;LinkedList底层使用链表实现,不一定连续的内存。

ArrayList查找效率较高,增删效率低;LinkedList与之相反,增删效率高,查找效率低。

这是为什么呢?

先説查找操作,ArrayList使用下标、连续内存,而LinkedList不连续,一个个next遍历的时候,ArrayList效率肯定较高;

(ArrayList查找的时间复杂度为1,而LinkedList的时间复杂度为n)

再说增加操作,由于ArrayList底层使用连续的数组,在增加元素时,首先需要考虑扩充数组容量,再然后可能要移位;而LinkedList只需要再开辟一个节点的空间,改变链表指针指向的方向即可。

例如在一个集合中有A,B,C,D四个元素,再执行list.add(1, "E");语句时

ArrayList需要将D,C,B三个元素依次复制向右移位一位,然后再插入新元素

                                                        

LinkedList只需要再开辟一个新的内存空间,改变链表指针指向的方向即可

删除操作类似。

 

LinkedList源码分析

在LinkedList中定义了三个全局变量,分别是int size,Node<E> first,Node<E> last

其中size是集合的大小,first是第一个节点,last是第二个节点。这也反应了LinkedList底层使用的是双向链表

first是查询操作的开始节点,last是添加操作的开始节点

接下来就很简单了,无非就是节点的first和last之间的相互赋值。

下面自己写一个代码,模拟LinkedList的实现过程

1、先定义节点信息

2、实现add方法

如果添加的元素是第一个,则链表的头节点是它,尾节点也是它;如果不是第一个了,则需要改变一下原来尾节点的指针

                                                 

最后新加节点作为尾部,链表长度+1.

3、实现get方法

get之前首先必须要判断下标是否越界:大于等于0小于size(下标越界应抛出IndexOutOfBoundsException异常,此处省略)

然后最简单的方法就是,逐个遍历,到元素index,当然JDK中不会写效率这么低的方法,它们充分利用双线机制和收尾两个节点,进行二分查找。

getNode方法是获取对应下标的节点(包括节点数据和前后指针)

4、实现remove方法

首先还是要判断下标是否要越界:大于等于0小于size,然后获取到要删除的节点,改变其前后节点的指针指向。

注意:删除收尾节点时,还要修改first或last变量,最后size-1

注意红框中的程序中的步骤:                       

第一步:将节点B指向的下一节点改为D,原来指向C的那条线算是断了;

第二步:将待删除节点C指向的前一节点赋值为null,提醒垃圾回收机制进行回收;

第三步:将节点D指向的前一节点改为B,原来指向C的那条线算是断了;

第四步:将待删除节点C指向的下一节点赋值为null,提醒垃圾回收机制进行回收;

最后再将待删除节点的数据部分置为null,进行回收内存。

5、实现按下标add方法

首先还是要判断下标是否要越界:大于等于0小于等于size(此处index可以等于size,相当于在最后add)

在这里还是要注意一下在首尾插入的情况

综上几个方法,只要带下标的方法,都利用了双向链表机制进行二分查找,增加了效率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值