1 package algorithms.ADT; 2 3 /****************************************************************************** 4 * Compilation: javac DoublyLinkedList.java 5 * Execution: java DoublyLinkedList 6 * Dependencies: StdOut.java 7 * 8 * A list implemented with a doubly linked list. The elements are stored 9 * (and iterated over) in the same order that they are inserted. 10 * 11 * % java DoublyLinkedList 10 12 * 10 random integers between 0 and 99 13 * 24 65 2 39 86 24 50 47 13 4 14 * 15 * add 1 to each element via next() and set() 16 * 25 66 3 40 87 25 51 48 14 5 17 * 18 * multiply each element by 3 via previous() and set() 19 * 75 198 9 120 261 75 153 144 42 15 20 * 21 * remove elements that are a multiple of 4 via next() and remove() 22 * 75 198 9 261 75 153 42 15 23 * 24 * remove elements that are even via previous() and remove() 25 * 75 9 261 75 153 15 26 * 27 ******************************************************************************/ 28 29 import java.util.ListIterator; 30 import java.util.NoSuchElementException; 31 32 import algorithms.util.StdOut; 33 import algorithms.util.StdRandom; 34 35 public class DoublyLinkedList<Item> implements Iterable<Item> { 36 private int N; // number of elements on list 37 private Node pre; // sentinel before first item 38 private Node post; // sentinel after last item 39 40 public DoublyLinkedList() { 41 pre = new Node(); 42 post = new Node(); 43 pre.next = post; 44 post.prev = pre; 45 } 46 47 // linked list node helper data type 48 private class Node { 49 private Item item; 50 private Node next; 51 private Node prev; 52 } 53 54 public boolean isEmpty() { return N == 0; } 55 public int size() { return N; } 56 57 // add the item to the list 58 public void add(Item item) { 59 Node last = post.prev; 60 Node x = new Node(); 61 x.item = item; 62 x.next = post; 63 x.prev = last; 64 post.prev = x; 65 last.next = x; 66 N++; 67 } 68 69 public ListIterator<Item> iterator() { return new DoublyLinkedListIterator(); } 70 71 // assumes no calls to DoublyLinkedList.add() during iteration 72 private class DoublyLinkedListIterator implements ListIterator<Item> { 73 private Node current = pre.next; // the node that is returned by next() 74 private Node lastAccessed = null; // the last node to be returned by prev() or next() 75 // reset to null upon intervening remove() or add() 76 private int index = 0; 77 78 public boolean hasNext() { return index < N; } 79 public boolean hasPrevious() { return index > 0; } 80 public int previousIndex() { return index - 1; } 81 public int nextIndex() { return index; } 82 83 public Item next() { 84 if (!hasNext()) throw new NoSuchElementException(); 85 lastAccessed = current; 86 Item item = current.item; 87 current = current.next; 88 index++; 89 return item; 90 } 91 92 public Item previous() { 93 if (!hasPrevious()) throw new NoSuchElementException(); 94 current = current.prev; 95 index--; 96 lastAccessed = current; 97 return current.item; 98 } 99 100 // replace the item of the element that was last accessed by next() or previous() 101 // condition: no calls to remove() or add() after last call to next() or previous() 102 public void set(Item item) { 103 if (lastAccessed == null) throw new IllegalStateException(); 104 lastAccessed.item = item; 105 } 106 107 // remove the element that was last accessed by next() or previous() 108 // condition: no calls to remove() or add() after last call to next() or previous() 109 public void remove() { 110 if (lastAccessed == null) throw new IllegalStateException(); 111 Node x = lastAccessed.prev; 112 Node y = lastAccessed.next; 113 x.next = y; 114 y.prev = x; 115 N--; 116 if (current == lastAccessed) 117 current = y; 118 else 119 index--; 120 lastAccessed = null; 121 } 122 123 // add element to list 124 public void add(Item item) { 125 Node x = current.prev; 126 Node y = new Node(); 127 Node z = current; 128 y.item = item; 129 x.next = y; 130 y.next = z; 131 z.prev = y; 132 y.prev = x; 133 N++; 134 index++; 135 lastAccessed = null; 136 } 137 138 } 139 140 public String toString() { 141 StringBuilder s = new StringBuilder(); 142 for (Item item : this) 143 s.append(item + " "); 144 return s.toString(); 145 } 146 147 // a test client 148 public static void main(String[] args) { 149 int N = Integer.parseInt(args[0]); 150 151 // add elements 1, ..., N 152 StdOut.println(N + " random integers between 0 and 99"); 153 DoublyLinkedList<Integer> list = new DoublyLinkedList<Integer>(); 154 for (int i = 0; i < N; i++) 155 list.add(StdRandom.uniform(100)); 156 StdOut.println(list); 157 StdOut.println(); 158 159 ListIterator<Integer> iterator = list.iterator(); 160 161 // go forwards with next() and set() 162 StdOut.println("add 1 to each element via next() and set()"); 163 while (iterator.hasNext()) { 164 int x = iterator.next(); 165 iterator.set(x + 1); 166 } 167 StdOut.println(list); 168 StdOut.println(); 169 170 // go backwards with previous() and set() 171 StdOut.println("multiply each element by 3 via previous() and set()"); 172 while (iterator.hasPrevious()) { 173 int x = iterator.previous(); 174 iterator.set(x + x + x); 175 } 176 StdOut.println(list); 177 StdOut.println(); 178 179 180 // remove all elements that are multiples of 4 via next() and remove() 181 StdOut.println("remove elements that are a multiple of 4 via next() and remove()"); 182 while (iterator.hasNext()) { 183 int x = iterator.next(); 184 if (x % 4 == 0) iterator.remove(); 185 } 186 StdOut.println(list); 187 StdOut.println(); 188 189 190 // remove all even elements via previous() and remove() 191 StdOut.println("remove elements that are even via previous() and remove()"); 192 while (iterator.hasPrevious()) { 193 int x = iterator.previous(); 194 if (x % 2 == 0) iterator.remove(); 195 } 196 StdOut.println(list); 197 StdOut.println(); 198 199 200 // add elements via next() and add() 201 StdOut.println("add elements via next() and add()"); 202 while (iterator.hasNext()) { 203 int x = iterator.next(); 204 iterator.add(x + 1); 205 } 206 StdOut.println(list); 207 StdOut.println(); 208 209 // add elements via previous() and add() 210 StdOut.println("add elements via previous() and add()"); 211 while (iterator.hasPrevious()) { 212 int x = iterator.previous(); 213 iterator.add(x * 10); 214 iterator.previous(); 215 } 216 StdOut.println(list); 217 StdOut.println(); 218 } 219 }