双向链表的每个结点除了数据域之外,还有一个前指针和后指针,分别指向前驱结点和后继结点(如果有前驱 / 后继的话)。另外,双向链表还有一个 first 指针,指向头节点;一个 last 指针,指向尾节点。
单向链表(1个数据域、1个指针域)要删除元素时,不但要找到删除的节点,还要找到删除节点的上一个节点(前驱),因为需要变更上一个节点中 next 的指针,但又因为它是单向链表,所以在删除的节点中并没有存储上一个节点的相关信息,那么我们就需要再查询一遍链表以找到上一个节点,这样就带来了一定的性能问题,所以就有了双向链表(1个数据域、2个指针域)。
//删除指定元素publicbooleanremove(Object o){if(o ==null){for(Node<E> x = first; x !=null; x = x.next){if(x.item ==null){unlink(x);returntrue;}}}else{for(Node<E> x = first; x !=null; x = x.next){if(o.equals(x.item)){unlink(x);returntrue;}}}returnfalse;}//删除指定下标的节点publicEremove(int index){checkElementIndex(index);returnunlink(node(index));}//删除指定节点,返回指定元素的值.Eunlink(Node<E> x){// assert x != null;finalE element = x.item;finalNode<E> next = x.next;//当前节点的后继finalNode<E> prev = x.prev;//当前节点的前驱if(prev ==null){
first = next;}else{
prev.next = next;//更新前驱节点的后继为当前节点的后继
x.prev =null;}if(next ==null){
last = prev;}else{
next.prev = prev;//更新后继节点的前驱为当前节点的前驱
x.next =null;}
x.item =null;
size--;
modCount++;return element;}
//删除表头元素publicEremoveFirst(){finalNode<E> f = first;if(f ==null)thrownewNoSuchElementException();returnunlinkFirst(f);}//删除表头节点,返回表头元素的值.privateEunlinkFirst(Node<E> f){// assert f == first && f != null;finalE element = f.item;finalNode<E> next = f.next;
f.item =null;
f.next =null;// help GC
first = next;//头指针指向后一个节点if(next ==null)
last =null;else
next.prev =null;//新头节点的前驱为null
size--;
modCount++;return element;}
//删除表尾元素publicEremoveLast(){finalNode<E> l = last;if(l ==null)thrownewNoSuchElementException();returnunlinkLast(l);}//删除表尾节点,返回表尾元素的值.privateEunlinkLast(Node<E> l){// assert l == last && l != null;finalE element = l.item;finalNode<E> prev = l.prev;
l.item =null;
l.prev =null;// help GC
last = prev;//尾指针指向前一个节点if(prev ==null)
first =null;else
prev.next =null;//新尾节点的后继为null
size--;
modCount++;return element;}
5. 获取元素
//获取表头元素publicEgetFirst(){finalNode<E> f = first;if(f ==null)thrownewNoSuchElementException();return f.item;}
//获取表尾元素publicEgetLast(){finalNode<E> l = last;if(l ==null)thrownewNoSuchElementException();return l.item;}
publicEget(int index){checkElementIndex(index);//先检查是否越界returnnode(index).item;}//获取指定下标的元素Node<E>node(int index){// assert isElementIndex(index);//根据下标是否超过链表长度的一半,来选择从头部开始遍历还是从尾部开始遍历.if(index <(size >>1)){Node<E> x = first;for(int i =0; i < index; i++)
x = x.next;return x;}else{Node<E> x = last;for(int i = size -1; i > index; i--)
x = x.prev;return x;}}