LinkedList類之詳解
阿新 • • 發佈:2018-12-15
LinkedList類
一、概述
List 介面的連結列表實現。
除了實現 List 介面外,LinkedList 類還為在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方法。這些操作允許將連結列表用作堆疊、佇列或雙端佇列。
二、特有方法
void
addFirst(E e)
將指定元素插入此列表的開頭。void
addLast(E e)
將指定元素新增到此列表的結尾。
E
getFirst()
返回此列表的第一個元素。E
getLast()
返回此列表的最後一個元素。
E
removeFirst()
移除並返回此列表的第一個元素。E
removeLast()
移除並返回此列表的最後一個元素。
E
get
(int index)
返回此列表中指定位置處的元素。
(1) addFirst(E e) 和 addLast(E e)
//連結串列長度
transient int size = 0;
//連結串列頭結點,起始為空
transient Node<E> first;
//連結串列尾結點,起始為空
transient Node<E> last;
//雙向連結串列
private static class Node<E> {
//本節點資料
E item;
//後繼節點
Node<E> next;
//前驅節點
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
public void addFirst(E e) {
linkFirst(e);
}
//頭插法
private void linkFirst(E e) {
final Node<E> f = first;
//建立本節點
//前驅節點賦值為空,本節點置入,後繼節點為原頭結點
final Node<E> newNode = new Node<>(null, e, f);
//頭結點賦值為newNode
first = newNode;
//如果原來頭結點為空,則說明原連結串列為空,則新節點即為頭結點也為尾結點
if (f == null)
last = newNode;
//如果不為空,則將原頭結點的前驅節點指向新節點
else
f.prev = newNode;
//長度+1
size++;
//修改次數+1
modCount++;
}
//尾插法
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
總結:
- 建立本節點
- 修改原頭結點、尾結點
- 本節點前後彼此連線
(2)getFirst() 和 getLast()
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
(3)removeFirst() 和 removeLast()
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
//獲取本節點內容
final E element = f.item;
//獲取後繼節點
final Node<E> next = f.next;
//本節點內容賦空
f.item = null;
//後繼節點賦空
//等待垃圾回收機制
f.next = null; // help GC
//頭結點指向該節點的後繼節點
first = next;
//如果後繼節點為空,則連結串列為空,尾結點賦空
if (next == null)
last = null;
else
//新頭結點前驅節點賦空
next.prev = null;
size--;
modCount++;
return element;
}
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
總結:
- 記住前驅節點或後繼節點
- 斷掉該節點連線
- 修改其他節點連線或修改頭尾結點
(4)get(int index)
public E get(int index) {
//是否越界,越界異常
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
//如果索引小於1/2,則從頭查詢
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
//如果索引大於1/2,則從尾查詢
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}