1. 程式人生 > >JAVA數據結構--LinkedList雙向鏈表

JAVA數據結構--LinkedList雙向鏈表

expected pty div expect ise tee override 另一個 lock

鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。 相比於線性表順序結構,操作復雜。由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的復雜度,比另一種線性表順序表快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而線性表和順序表相應的時間復雜度分別是O(logn)和O(1)。
技術分享 本文是按照《數據結構與算法分析》一書實現的雙向鏈表的內容,個人認為鏈表的難點在於插入和刪除的操作,但這點也是鏈表的優勢之處。
  1
package DataStructures; 2 3 import java.util.ConcurrentModificationException; 4 import java.util.Iterator; 5 import java.util.NoSuchElementException; 6 7 public class MyLinkedList<AnyType> implements Iterable<AnyType> { 8 /* 9 * data當前節點的值 10 * prev當前節點的前綴節點
11 * next當前節點的後綴節點 12 * */ 13 private static class Node<AnyType>{ 14 public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){ 15 data=d; 16 prev=p; 17 next=n; 18 } 19 public AnyType data; 20 public
Node<AnyType> prev; 21 public Node<AnyType> next; 22 } 23 public MyLinkedList() { 24 doClear(); 25 // TODO Auto-generated constructor stub 26 } 27 public void clear(){ 28 doClear(); 29 } 30 /* doClear() 31 * 將頭結點置空 32 * 尾節點的前綴置為頭節點 33 * 頭結點的後綴為尾節點 34 * */ 35 private void doClear(){ 36 beginMarker=new Node<AnyType>(null, null, null); 37 endMarker=new Node<AnyType>(null, beginMarker, null); 38 beginMarker.next=endMarker; 39 theSize=0; 40 modCount++; 41 } 42 43 public int size(){ 44 return theSize; 45 } 46 public boolean isEmpty(){ 47 return size()==0; 48 } 49 /* 50 * 在鏈表尾部插入新節點 51 * */ 52 public boolean add(AnyType x){ 53 add(size(), x); 54 return true; 55 } 56 /* 57 * 在鏈表中插入新節點 58 * */ 59 public void add(int idx,AnyType x){ 60 addBefore(getNode(idx,0,size()),x); 61 } 62 public AnyType get(int idx){ 63 return getNode(idx).data; 64 } 65 /* 66 * 修改某個節點的值 67 * */ 68 public AnyType set(int idx,AnyType newVal){ 69 Node<AnyType> p=getNode(idx);//p為需要修改的節點 70 AnyType oldVal=p.data; 71 p.data=newVal; 72 return oldVal; 73 } 74 public AnyType remove(int idx){ 75 return remove(getNode(idx)); 76 } 77 78 /* 79 * 在p節點前插入新的節點 80 * */ 81 private void addBefore(Node<AnyType> p,AnyType x){ 82 Node<AnyType> newNode=new Node<>(x, p.prev, p);//新節點的前綴為p的前綴,後綴為p 83 newNode.prev.next=newNode;//新節點的前綴的後綴為新節點 84 p.prev=newNode;//p節點的前綴為p 85 theSize++; 86 modCount++; 87 } 88 private AnyType remove(Node<AnyType> p){ 89 p.next.prev=p.prev; 90 p.prev.next=p.next; 91 theSize--; 92 modCount++; 93 return p.data; 94 } 95 private Node<AnyType> getNode(int idx){ 96 return getNode(idx,0,size()-1); 97 } 98 /* 99 * 獲得某個節點 100 * */ 101 private Node<AnyType> getNode(int idx,int lower,int upper){ 102 Node<AnyType> p; 103 if(idx<lower||idx>upper) 104 throw new IndexOutOfBoundsException(); 105 if(idx<size()/2){//如果節點在前半部分,將從頭結點向後開始遍歷 106 p=beginMarker.next; 107 for(int i=0;i<idx;i++) 108 p=p.next; 109 } 110 else {//如果節點在後半部分,將從尾節點向前遍歷 111 p=endMarker; 112 for(int i=size();i>idx;i--) 113 p=p.prev; 114 } 115 return p; 116 } 117 @Override 118 public Iterator<AnyType> iterator() { 119 // TODO Auto-generated method stub 120 return new LinkedListIterator(); 121 } 122 private class LinkedListIterator implements Iterator<AnyType>{ 123 private Node<AnyType> current=beginMarker; 124 private int expectedModCount=modCount; 125 private boolean okToRemove=false; 126 public boolean hasNext(){ 127 return current!=endMarker; 128 } 129 public AnyType next(){ 130 if(modCount!=expectedModCount) 131 throw new ConcurrentModificationException(); 132 if(!hasNext()) 133 throw new NoSuchElementException(); 134 AnyType nextItem=current.data; 135 current=current.next; 136 okToRemove=true; 137 return nextItem; 138 } 139 public void remove(){ 140 if(modCount!=expectedModCount) 141 throw new ConcurrentModificationException(); 142 if(!okToRemove) 143 throw new IllegalStateException(); 144 MyLinkedList.this.remove(current.prev); 145 expectedModCount++; 146 okToRemove=false; 147 } 148 } 149 150 private int theSize;//鏈表的長度 151 private int modCount;//鏈表改動的次數 152 private Node<AnyType> beginMarker;//頭結點 153 private Node<AnyType> endMarker;//尾節點 154 }

JAVA數據結構--LinkedList雙向鏈表