Build a LinkedList yourself

Keywords: Java github

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

Posted by muitine on Thu, 17 Oct 2019 05:42:17 -0700