//E->anyType object private static class Node<E> { //數據項 private E data; //指向next節點的引用 private Node<E> next; //構造 public Node(E data, Node<E> next) { this.data = data; this.next = next; } }
private Node<E> head = null;
public void addFirst(E item) { head = new Node<E>(item, head); }
public void insertBefore(E key, E toInsert) { //若head爲null,即鏈表爲空,不存在目標節點 直接返回 if(head == null) return; //若head指向的鏈表第一個節點 就是目標節點,即要把新建節點插入鏈表首部 if(head.data.equals(key)) { addFirst(toInsert); return; } Node<E> prev = null; Node<E> curr = head; //curr定義了 指向當前節點,prev指向當前節點的上個節點。一直順序查找,若找到目標節點(數據爲key),則curr指向目標節點,prev指向了目標節點的上個節點。 while(curr != null && !curr.data.equals(key)) { prev = curr; curr = curr.next; } //若curr不爲空,即找到目標節點,在curr和prev之間插入了新節點(數據爲toInsert)。若curr爲null,即沒找到。 if(curr != null) prev.next = new Node<E>(toInsert, curr); }
public void insertAfter(E key, E toInsert) { Node<E> curr = head; //查找目標節點,找到即curr指向目標節點 while(curr != null && !curr.data.equals(key)) { curr = curr.next; } //curr不爲null,即找到目標節點。在以後插入便可。 if(curr != null) curr.next = new Node<E>(toInsert, curr.next); }
public void addLast(E item) { if(head == null) { addFirst(item); } else { Node<E> tmp = head; while(tmp.next != null) tmp = tmp.next; tmp.next = new Node<E>(item, null); } }
public void remove(E key) { //head爲null,即鏈表爲空 if(head == null) throw new RuntimeException("linkedlist is null, cannot delete"); //鏈表第一個節點即目標節點,改變head指向下個節點就能夠了。 if(head.data.equals(key)) { head = head.next; return; } Node<E> prev = null; Node<E> curr = head; //查找,若找到即curr指向目標節點,prev指向目標節點的上個節點 while(curr != null && !curr.data.equals(key)) { prev = curr; curr = curr.next; } //curr爲null,即沒找到 if(curr == null) throw new RuntimeException("cannot find your node, cannot delete"); //curr不爲null,刪除目標節點(即改變prev的next 指向curr的next便可) prev.next = curr.next; }
transient int size = 0; /** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first;//指向首部(第一個節點) /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ 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; } }
/** * Links e as first element. */ private void linkFirst(E e) { //f指向first指向的節點。即f和first同時指向第一個節點。f在方法中標誌 鏈表插入前的第一個節點 final Node<E> f = first; //建立新的節點,節點的prev指向null,next指向f(即鏈表插入前第一個節點) final Node<E> newNode = new Node<>(null, e, f); //first指向新節點(鏈表首部已改變) first = newNode; if (f == null) //若f爲null,即插入前鏈表是空的,插入到新節點既是開始節點也是結束節點,因此last也指向了它 last = newNode; else //若是f不爲空,則讓f(插入前的第一個節點)的prev指向新節點就完成了。 f.prev = newNode; size++; modCount++; }
/** * Inserts element e before non-null Node succ. */ void linkBefore(E e, Node<E> succ) { // assert succ != null; //這裏把succ稱爲目標節點。succ在這裏是已經查找到並存在的,查找過程可參考單鏈表中相關代碼。 //用pred指向 目標節點succ的上個節點。 final Node<E> pred = succ.prev; //新建節點,prev指向pred 即新建節點的prev指向目標節點的上個節點,next指向目標節點 final Node<E> newNode = new Node<>(pred, e, succ); //目標節點的prev指向 新建節點 succ.prev = newNode; if (pred == null) //若pred爲null 是目標節點上個節點爲null,即鏈表插入前只有一個節點,因此first會指向新建節點。 first = newNode; else //若pred不爲null,目標節點的上個節點的next指向新節點 pred.next = newNode; size++; modCount++; }
/** * Links e as last element. */ 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++; }
/** * Removes the first occurrence of the specified element from this list, * if it is present. If this list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * {@code i} such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ public boolean remove(Object o) { //這裏就是區分o是否爲null,找到第一個指定element的節點,經過unlink刪除。 if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; } /** * Unlinks non-null node x. */ E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { //prev爲null 即x是首部(第一個節點),first指向next便可 first = next; } else { //prev不爲null,x與prev之間關聯即斷開。prev的next指向next了,x的prev爲null prev.next = next; x.prev = null; } //同prev處理相似,斷開x與next聯繫 if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
private Node<E> head = null; private Node<E> tail = null; private class Node<E> { E value; Node<E> next; public Node(E value) { this.value = value; } } //往尾部(即tail節點以後)添加節點 public void addNode(E value) { Node<E> newNode = new Node<>(value); if (head == null) { //head爲null,即鏈表爲空,head指向新建節點。 head = newNode; } else { tail.next = newNode; } //tail指向新節點,即新節點至關於鏈表的尾部 tail = newNode; //tail.next即新節點next指向head,造成環 tail.next = head; } //查找,鏈表中是否包含數據爲searchValue的節點 public boolean containsNode(E searchValue) { Node<E> currentNode = head; if (head == null) { return false; } else { //以head開始依次向後查找,直到碰到的還是head中止。找到返回 do { if (currentNode.value == searchValue) { return true; } currentNode = currentNode.next; } while (currentNode != head); return false; } } //刪除查找到的第一個數據爲valueToDelete的節點 public void deleteNode(E valueToDelete) { Node<E> currentNode = head; if (head != null) { if (currentNode.value == valueToDelete) { //head節點且值爲valueToDelete head = head.next; tail.next = head; } else { //以head開始依次向後查找,直到碰到的還是head中止。找到刪除 do { Node<E> next = currentNode.next; if (next.value == valueToDelete) { currentNode.next = next.next; break; } currentNode = currentNode.next; } while (currentNode != head); } } }
簡單作了個表格node
鏈表
|
數組
|
動態分配:須要時才分配內存
|
固定分配:大小固定,new時即分配全部內存
|
分散存儲:內存中不連續存儲
|
連續存儲:內存中連續存儲
|
總量限制:因爲分散存儲,受內存總量限制
|
使用限制:因爲連續存儲,若無合適連續控件即沒法完成分配,且容易造成內存碎片
|
插入/刪除方便:改變節點中指向next的或者prev的引用便可
|
插入/刪除代價大:需建立新數組並移動元素
|
有內存浪費:節點中需額外存儲next或prev的信息
|
無內存浪費:數組元素只存放數據
|
順序訪問:在某個節點沿某一方向只能逐一訪問
|
隨機訪問:能夠直接計算獲得某一元素的地址
|
操做
|
鏈表
|
數組
|
訪問(訪問第N個元素)
|
O(n)
|
O(1)
|
插入到首部
|
O(1)
|
O(n)
|
插入到尾部
|
有尾部引用tail:O(1)
無尾部引用O(n)
|
O(n)
|
插入到中部
|
查找時間+O(1)~=O(n)
|
O(n) |
查找
|
O(n)
|
O(n) |
刪除 |
相似插入,看刪除位置或者鏈表的設計
|
O(n)
|