Java双向链表(通过源码分析)

 

                                                    

如上图就是我们的链表的结构,这些节点游离在内存中,位置不连续;一个节点包括三个部分:prior,element,next;prior部分指向上一个节点,如果prior的值为null,则表示它是第一个节点,也就是链表的开始;element指向储存对象的地址;next与prior相似,next指向下一个节点,如果为null,则为最后一个节点。这种结构使它变更的能力大大增强,变更只需要修改它的前后链接而不需要考虑重新创建,但是这种模式没有下角标会使它的查询变慢;

接下来我们来看看它的java源码:

以LinkedList为例:

这个类里边有size表示表的长度,而first和last表示它第一个元素和最后一个元素,我们可以看出使用链表时我们可以不需要查询的得到第一个节点和最后一个节点;

我们可以再深入Node内查看它每一个节点的构成:

 它的每一个节点都有三个属性,三个属性通过构造方法分别赋值。

之后我们可以深入它的一些api对他进行了解:

bolean add(E  e)

->

 我们可以看到,它是创建了一个新的node对象,将原先最后一个节点指向新节点的prev属相,e指向它真正的值,因为它是直接加在最后的,所以它的next属性指向为null,这样这个对象就建好了。但是我们还要对LinkedList最后一位进行变更,也就是last=新对象;还有就是对它前一节点的next属相进行变更,这里有两种情况:它没有前一节点(也就是它是第一个节点)和它有前一个节点,如果没有前一个节点,那他就直接赋值为第一个节点,如果有前一个节点,那么我们改变它前一个节点next属相指向它,这时我们基本步骤完毕,长度加一和操作数加一后我们就可以返回;

我们再看它的重载方法:

void add(int index, E element)  (注意,这个index不是它的下标,因为链表没有下标,这也是它查询中间元素困难的原因)

这个api比上一个就复杂了,它有三个点checkPositionIndex(index)和linkBefore(element, node(index))以及linkBefore(element, node(index))中的运用到的node(index)方法;其中checkPositionIndex(index)是最简单的,就是判断index是否合规,不合规则抛出数组下标越界异常(不是真正的下标)这里就不展示它代码了,然后我们说linkBefore(element, node(index))中的运用到的node(index)方法,这个方法是根据index(这里应该说它节点的位置)获取这个节点对象,这里我们来看看它的源码:

 它只能一个节点一个节点的找,所以说效率很慢,但我们还是对它做了优化,就是判断它离哪个(first/last)元素近,我们就可以从哪一个开始找,遍历到正确的次数返回元素;然后会到我们的linkBefore(element, node(index))方法(不要忘了之前还有一个判断是不是第一个节点,是的话直接调用bolean add(E  e)添加),我们来看看它的源码:

这里将获取到的节点的prev直接赋值给新对象的prev属性,并且新对象的next指向了了获取到的对象,到此我们的新节点就产生了,但是我们还要改变获取节点的prev指向新对象以及它前一个节点的next指向新对象;之后改变长度以及修改次数返回,我们的过程就完成了;

之后还有删除api:

E remove(int index)

这里判断参数格式和获取对应节点的方法就不再赘述了,我们直接看它的删除过程

 获取了对应节点,也就获取了对应节点前一个节点和后一个节点,删除这个节点的同时连接接它前一个节点和后一个节点,最后改变长度和操作数返回,我们就完成了删除;

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值