《数据结构和Java集合框架第三版》读书笔记(六)LinkedList双向链表

JDK6和JDK7的LinkedList的算法有一些区别。JDK6是:带哨兵的环形双向链表,JDK7是不带哨兵、但是有first(头节点)和last(尾节点)的双向非循环链表。哨兵的好处是使得代码更简洁,但并不能降低对链表的操作的渐进时间界;坏处是如果有很多较短链表,使用哨兵会造成存储空间的浪费(哨兵是需要new一个Entry的)。

一,JDK6:带哨兵的环形双向链表

哨兵是个哑元,它表示NIL,包含和其他元素一样的各个域。可以简化边界条件。

private transient Entry<E>header =new Entry<E>(null,null,null);

哨兵header处于链表头和链表尾之间,哨兵的next指向链表头,哨兵的prev指向表尾,表头的prev指向哨兵,表尾的next指向哨兵。这样使得每个元素Entry对象都有一个前置Entry对象和一个后置Entry对象,从而简化了表头和表尾的边界条件,简化了链表插入和删除的代码

1,构造函数:

public LinkedList() {header.next =header.previous =header; }


哨兵首尾相连,形成环形链表。

2,插入元素


默认add方法在表尾添加元素。

下边这个方法更具有普遍性

在index位置插入元素element

public avoid add(int index,Object element){
    addBefore(element,(index==size?header:entry(index)));
}

如果index==size,则在表尾插入元素(由于环形双向链表的表尾的next是哨兵header,因此相当于在哨兵header之前插入一个元素,即addBefore(header))  这个操作的时间复杂度可以认为是O(1)级别的

如果index不等于size,则需要entry(index)函数查找index位置的元素了。

由于这是一个环形双向链表,可以比较index和(size/2),来判断应该从header字段开始正向搜索还是逆向搜索

最坏情形是index在中间,要进行n/2次迭代(for循环次数),所以worstTime(n)为O(n)


                                   上边那张图里entry(1)的结果,找到了“Eric”元素

addBefore方法:



              准备在阶段e前插入元素为Don的新节点,创建这个新节点newEntry,将其前驱指针域指向e的前驱,后继指针域指向e



                         调整newEntry的前驱对象的后继指针域指向newEntry,调整newEntry的后继对象的前驱指针域指向newEntry



结果

3,删除元素

remove函数比较好写

首先要查找出节点,如果是remove(index),最坏情形迭代n/2次;如果是remove(Object),最坏情形迭代n次。总之还是O(n)

找到这个节点后,只需要改变被删除的元素的前驱对象的next和后继对象的prev就好了。这一步的操作的worstTime(n)是O(1).


总结:说LinkedList适合随机增删是有前提的,即链表不能太大。因为查找节点会耗费大量时间。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值