数据结构 - 单链表
单链表:
简单的链表结构,对象方式实现。通常,单链表实际很少使用,但不失为一个好的学习工具。
没有经过严格的测试,用于学习理解,如有错误,欢迎指正。
复杂度:
头插和尾插:O(1)
中间插入:O(n)
头删:O(1)
尾删:O(n)
中间删:O(n)
按元素删:O(n)
查元素:O(n)
改元素:O(n)
获取长度:O(1)
获取大小:O(1)
1 package collections; 2 3 import java.util.Iterator; 4 5 public class SingleLinkedList<T> implements Iterable { 6 private Node<T> head; 7 private Node<T> cur; 8 private int len; 9 10 @Override 11 public Iterator iterator() { 12 return new SingleLinkedListIterator<>(head); 13 } 14 15 public SingleLinkedList() { 16 this.head = new Node<>(null, null); 17 this.cur = head; 18 this.len = 0; 19 } 20 21 /** 22 * add before 23 * 24 * @param var Node{var} 25 */ 26 public void push(T var) { 27 head.setNext(new Node<>(var, head.getNext())); 28 len++; 29 } 30 31 /** 32 * add last 33 * 34 * @param var Node{var} 35 */ 36 public void append(T var) { 37 Node<T> newNode = new Node<>(var, null); 38 cur.setNext(newNode); 39 cur = newNode; 40 len++; 41 } 42 43 /** 44 * add element by index 45 * 46 * @param index add position 47 * @param element element 48 */ 49 public void insert(int index, T element) { 50 if (isEmpty() && index == 0) { 51 push(element); 52 } 53 checkIndex(index); 54 Node<T> lastNode = getLastNode(index); 55 lastNode.setNext(new Node<>(element, lastNode.getNext())); 56 len++; 57 } 58 59 /** 60 * remove last 61 */ 62 public void pop() { 63 if (isEmpty()) { 64 return; 65 } 66 Node<T> lastNode = head; 67 while (lastNode.getNext().getNext() != null) { 68 lastNode = lastNode.getNext(); 69 } 70 lastNode.setNext(null); 71 cur = lastNode; 72 len--; 73 } 74 75 /** 76 * check index 77 * 78 * @param index position 79 */ 80 private void checkIndex(int index) { 81 if (index > len - 1 || index < 0) { 82 throw new ArrayIndexOutOfBoundsException(); 83 } 84 } 85 86 /** 87 * get last node by index 88 * 89 * @param index current index 90 * @return last node 91 */ 92 private Node<T> getLastNode(int index) { 93 int i = 0; 94 Node<T> lastNode = head; 95 while (i++ != index && lastNode.getNext().getNext() != null) { 96 lastNode = lastNode.getNext(); 97 } 98 return lastNode; 99 } 100 101 /** 102 * remove node by index 103 * 104 * @param index node index from 0 to (length - 1) 105 */ 106 public void pop(int index) { 107 checkIndex(index); 108 // left remove 109 if (index == 0) { 110 Node<T> firstNode = head.getNext(); 111 head.setNext(firstNode.getNext()); 112 firstNode.setNext(null); 113 len--; 114 if (len == 0) { 115 cur = head; 116 } 117 return; 118 } 119 // right remove 120 if (index == len - 1) { 121 pop(); 122 return; 123 } 124 // center remove 125 Node<T> lastNode = getLastNode(index); 126 Node<T> curNode = lastNode.getNext(); 127 lastNode.setNext(curNode.getNext()); 128 curNode.setNext(null); 129 len--; 130 } 131 132 /** 133 * remove element by target if existed 134 * 135 * @param target element removed 136 */ 137 public void remove(T target) { 138 Node<T> lastNode = head; 139 Node<T> curNode = head; 140 while (curNode != null && curNode.getVar() != target) { 141 lastNode = curNode; 142 curNode = curNode.getNext(); 143 } 144 if (curNode == cur) { 145 lastNode.setNext(null); 146 cur = lastNode; 147 len--; 148 return; 149 } 150 if (curNode != null) { 151 lastNode.setNext(curNode.getNext()); 152 curNode.setNext(null); 153 len--; 154 } 155 } 156 157 /** 158 * check element exist 159 * 160 * @param element element checked 161 * @return if exist return index, if not return -1 162 */ 163 public int contain(T element) { 164 if (isEmpty()) { 165 return -1; 166 } 167 int i = 0; 168 Node<T> currentNode = head.getNext(); 169 while (currentNode.getVar() != element) { 170 currentNode = currentNode.getNext(); 171 if (currentNode == null) { 172 return -1; 173 } 174 i++; 175 } 176 return i; 177 } 178 179 /** 180 * update element value 181 * 182 * @param index element position 183 * @param element element updated 184 */ 185 public void update(int index, T element) { 186 if (isEmpty()) { 187 return; 188 } 189 checkIndex(index); 190 getLastNode(index).getNext().setVar(element); 191 } 192 193 /** 194 * get length 195 * 196 * @return size of list 197 */ 198 public int length() { 199 return len; 200 } 201 202 /** 203 * check empty 204 * 205 * @return if empty true, else false 206 */ 207 public boolean isEmpty() { 208 return len == 0; 209 } 210 211 } 212 213 class Node<T> { 214 private T var; 215 private Node<T> next; 216 217 public Node(T var, Node<T> next) { 218 this.var = var; 219 this.next = next; 220 } 221 222 public T getVar() { 223 return var; 224 } 225 226 public void setVar(T var) { 227 this.var = var; 228 } 229 230 public Node<T> getNext() { 231 return next; 232 } 233 234 public void setNext(Node<T> next) { 235 this.next = next; 236 } 237 } 238 239 class SingleLinkedListIterator<T> implements Iterator { 240 241 private Node<T> cursor; 242 243 public SingleLinkedListIterator(Node<T> node) { 244 this.cursor = node; 245 } 246 247 @Override 248 public boolean hasNext() { 249 if (cursor == null) { 250 return false; 251 } 252 boolean flag = cursor.getNext() != null; 253 cursor = cursor.getNext(); 254 return flag; 255 } 256 257 @Override 258 public Object next() { 259 return cursor; 260 } 261 }
知止而后有定;定而后能静;静而后能安;安而后能虑;虑而后能得。