Build a LinkedList yourself
1. principle
LinkedList is a dynamic array based on double linked list. It is efficient to add and delete data, just change the pointer point, but the average efficiency of accessing data is low, so it needs to traverse the linked list. Therefore, LinkedList is good at some insertion and deletion operations, which is not conducive to retrieval operations. LinkedList and ArrayList are two lists that are often used in our code. Therefore, a simple version of LinkedList, MyLinkedList, is implemented by customization.
2. public API
void clear() -- set null
boolean isEmpty(), null
int size() --- returns the len gt h of the linked list
AnyType get(int idx) - > retrieve elements by index
AnyType set(int idx) - > follow new elements according to index
boolean add(AnyType x) - > add element x
boolean add(AnyType x, int idx) - > add element x according to index
AnyType remove(int idx) - > delete element x according to index
String toString() -- print linked list
3. Diagram core operation
-
Data structure of a Node node class
-
The doClear() method initializes a double linked list, first defines a header node beginMarker, then defines a tail node endMarker, the precursor points to the header node, and the subsequent of the header node points to the tail node.
-
To add an element, first define a node of the added element x, so that its precursor points to the previous node of the inserted position, and then points to the node of the inserted position. This is the first step, and then point the next of the inserted previous node to this node, and the prev of the inserted node points to this node.
Node<AnyType> newNode = new Node<>(x, p.prev, p); // ①②
newNode.prev.next = newNode; // ③
p.prev = newNode; // ④Of course, steps 3 and 4 can be combined:
Node<AnyType> newNode = new Node<>(x, p.prev, p); // ①②
p.prev = p.prev.next = newNode; // ③④I didn't expect that the above four steps can all be combined into:
p.prev = p.prev.next = new Node<>(x, p.prev, p); // ①②③④
Brilliant!
-
Delete the element, find the corresponding node p according to the index, point the prev of p to the precursor of p, and point the next of p to the successor of p.
p.next.prev = p.prev;
p.prev.next = p.next;
-
The search node getNode and LinkedList can insert and delete elements quickly and easily, but for the search elements, it is slow. We can divide the index into the first half and the second half. If the index is in the first half, we will traverse the linked list in the backward direction. Similarly, if the index is in the second half, we will start from the terminal and traverse the list in the forward direction. Linked list, this can improve the retrieval speed.
//Find backward from the beginning of the node
if (idx < size() / 2) {
p = beginMarker.next;
for (int i = 0; i < idx; i++) {
p = p.next;
}
}
//Looking forward from the tail node
else {
p = endMarker;
for (int i = size(); i > idx; i--) {
p = p.prev;
}
}
4. Implementation of mylinkedlist code
1 package com.hx.list; 2 3 /** 4 * @author: wenhx 5 * @date: Created in 2019/10/17 16:11 6 * @description: Using double linked list to realize MyLinkedList 7 */ 8 public class MyLinkedList<AnyType> implements Iterable<AnyType> { 9 10 11 private int theSize; 12 private int modCount = 0; 13 private Node<AnyType> beginMarker; 14 private Node<AnyType> endMarker; 15 16 /** 17 * Inner class, defining nodes of linked list 18 */ 19 private static class Node<AnyType> { 20 21 public AnyType data; 22 public Node<AnyType> prev; 23 public Node<AnyType> next; 24 25 public Node(AnyType d, Node<AnyType> p, Node<AnyType> n) { 26 data = d; 27 prev = p; 28 next = n; 29 } 30 } 31 32 /** 33 * constructor 34 */ 35 public MyLinkedList() { 36 doClear(); 37 } 38 39 /** 40 * Sentence blank 41 */ 42 public boolean isEmpty() { 43 return size() == 0; 44 } 45 46 /** 47 * empty 48 */ 49 public void clear() { 50 doClear(); 51 } 52 53 54 /** 55 * Return the length of the linked list 56 */ 57 public int size() { 58 return theSize; 59 } 60 61 /** 62 * Retrieve elements by index 63 */ 64 public AnyType get(int idx) { 65 return getNode(idx).data; 66 } 67 68 /** 69 * Follow new elements according to index 70 */ 71 public AnyType set(int idx, AnyType newVal) { 72 Node<AnyType> p = getNode(idx); 73 AnyType oldVal = p.data; 74 p.data = newVal; 75 return oldVal; 76 } 77 78 /** 79 * Add element x 80 */ 81 public boolean add(AnyType x) { 82 add(size(), x); 83 return true; 84 } 85 86 /** 87 * Add elements according to index 88 */ 89 public void add(int idx, AnyType x) { 90 addBefore(getNode(idx, 0, size()), x); 91 } 92 93 /** 94 * Delete elements according to index 95 */ 96 public AnyType remove(int idx) { 97 return remove(getNode(idx)); 98 } 99 100 /** 101 * Print list 102 */ 103 public String toString() { 104 StringBuilder sb = new StringBuilder("[ "); 105 106 for (AnyType x : this) { 107 sb.append(x + " "); 108 } 109 sb.append("]"); 110 111 return new String(sb); 112 } 113 114 /** 115 * Clear list (Implementation) 116 */ 117 private void doClear() { 118 beginMarker = new Node<>(null, null, null); 119 endMarker = new Node<>(null, beginMarker, null); 120 beginMarker.next = endMarker; 121 theSize = 0; 122 modCount++; 123 } 124 125 /** 126 * Retrieve nodes by index 127 */ 128 private Node<AnyType> getNode(int idx) { 129 return getNode(idx, 0, size() - 1); 130 } 131 132 /** 133 * Search node 134 */ 135 private Node<AnyType> getNode(int idx, int lower, int upper) { 136 Node<AnyType> p; 137 138 if (idx < lower || idx > upper) { 139 throw new IndexOutOfBoundsException("getNode index: " + idx + "; size: " + size()); 140 } 141 142 if (idx < size() / 2) { 143 p = beginMarker.next; 144 for (int i = 0; i < idx; i++) { 145 p = p.next; 146 } 147 } else { 148 p = endMarker; 149 for (int i = size(); i > idx; i--) { 150 p = p.prev; 151 } 152 } 153 154 return p; 155 } 156 157 /** 158 * Insertion node 159 */ 160 private void addBefore(Node<AnyType> p, AnyType x) { 161 Node<AnyType> newNode = new Node<>(x, p.prev, p); 162 newNode.prev.next = newNode; 163 p.prev = newNode; 164 theSize++; 165 modCount++; 166 } 167 168 /** 169 * Delete node p 170 */ 171 private AnyType remove(Node<AnyType> p) { 172 p.next.prev = p.prev; 173 p.prev.next = p.next; 174 theSize--; 175 modCount++; 176 177 return p.data; 178 } 179 180 181 /** 182 * Returns an iterator object for traversing the linked list 183 */ 184 public java.util.Iterator<AnyType> iterator() { 185 return new LinkedListIterator(); 186 } 187 188 /** 189 * LinkedListIterator Implementation of iterator 190 */ 191 private class LinkedListIterator implements java.util.Iterator<AnyType> { 192 193 private Node<AnyType> current = beginMarker.next; 194 private int expectedModCount = modCount; 195 private boolean okToRemove = false; 196 197 public boolean hasNext() { 198 return current != endMarker; 199 } 200 201 public AnyType next() { 202 if (modCount != expectedModCount) { 203 throw new java.util.ConcurrentModificationException(); 204 } 205 if (!hasNext()) { 206 throw new java.util.NoSuchElementException(); 207 } 208 209 AnyType nextItem = current.data; 210 current = current.next; 211 okToRemove = true; 212 return nextItem; 213 } 214 215 public void remove() { 216 if (modCount != expectedModCount) { 217 throw new java.util.ConcurrentModificationException(); 218 } 219 if (!okToRemove) { 220 throw new IllegalStateException(); 221 } 222 223 MyLinkedList.this.remove(current.prev); 224 expectedModCount++; 225 okToRemove = false; 226 } 227 } 228 229 230 /** 231 * Main method: used to test MyLinkedList 232 */ 233 public static void main(String[] args) { 234 MyLinkedList<Integer> myLinkedList = new MyLinkedList<>(); 235 236 for (int i = 0; i < 10; i++) { 237 myLinkedList.add(i); 238 } 239 for (int i = 20; i < 30; i++) { 240 myLinkedList.add(0, i); 241 } 242 243 System.out.println(myLinkedList.toString()); 244 System.out.println("----------"); 245 myLinkedList.remove(0); 246 myLinkedList.remove(myLinkedList.size() - 1); 247 System.out.println(myLinkedList); 248 System.out.println("----------"); 249 java.util.Iterator<Integer> itr = myLinkedList.iterator(); 250 while (itr.hasNext()) { 251 itr.next(); 252 itr.remove(); 253 System.out.println(myLinkedList); 254 } 255 } 256 }
Finish, sprinkle flowers, a mini LinkedList will be finished, and write another Mini ArrayList next time you have time...
Postscript:
If there is something wrong, you can feed back to the editor, exchange and learn together, and make progress together.
Personal blog address: https://www.cnblogs.com/q964024886/
GitHub address: https://github.com/wenhaixiong