001package components.list; 002 003import java.util.Iterator; 004import java.util.NoSuchElementException; 005 006/** 007 * {@code List} represented as a singly linked list, done "bare-handed", with 008 * implementations of primary methods. 009 * 010 * <p> 011 * Execution-time performance of all methods implemented in this class is O(1). 012 * </p> 013 * 014 * @param <T> 015 * type of {@code List} entries 016 * @convention <pre> 017 * $this.leftLength >= 0 and 018 * [$this.rightLength >= 0] and 019 * [$this.preStart is not null] and 020 * [$this.lastLeft is not null] and 021 * [$this.finish is not null] and 022 * [$this.preStart points to the first node of a singly linked list 023 * containing $this.leftLength + $this.rightLength + 1 nodes] and 024 * [$this.lastLeft points to the ($this.leftLength + 1)-th node in 025 * that singly linked list] and 026 * [$this.finish points to the last node in that singly linked list] and 027 * [$this.finish.next is null] 028 * </pre> 029 * @correspondence <pre> 030 * this = 031 * ([data in nodes starting at $this.preStart.next and running through 032 * $this.lastLeft], 033 * [data in nodes starting at $this.lastLeft.next and running through 034 * $this.finish]) 035 * </pre> 036 */ 037public class List2<T> extends ListSecondary<T> { 038 039 /** 040 * Node class for singly linked list nodes. 041 */ 042 private final class Node { 043 044 /** 045 * Data in node. 046 */ 047 private T data; 048 049 /** 050 * Next node in singly linked list, or null. 051 */ 052 private Node next; 053 054 } 055 056 /** 057 * "Smart node" before front node of singly linked list. 058 */ 059 private Node preStart; 060 061 /** 062 * Last left node of singly linked list in this.left. 063 */ 064 private Node lastLeft; 065 066 /** 067 * Finish node of linked list. 068 */ 069 private Node finish; 070 071 /** 072 * Length of this.left. 073 */ 074 private int leftLength; 075 076 /** 077 * Length of this.right. 078 */ 079 private int rightLength; 080 081 /** 082 * Creator of initial representation. 083 */ 084 private void createNewRep() { 085 this.preStart = new Node(); 086 this.preStart.next = null; 087 this.finish = this.preStart; 088 this.lastLeft = this.preStart; 089 this.leftLength = 0; 090 this.rightLength = 0; 091 } 092 093 /** 094 * No-argument constructor. 095 */ 096 public List2() { 097 this.createNewRep(); 098 } 099 100 @SuppressWarnings("unchecked") 101 @Override 102 public final List2<T> newInstance() { 103 try { 104 return this.getClass().getConstructor().newInstance(); 105 } catch (ReflectiveOperationException e) { 106 throw new AssertionError( 107 "Cannot construct object of type " + this.getClass()); 108 } 109 } 110 111 @Override 112 public final void clear() { 113 this.createNewRep(); 114 } 115 116 @Override 117 public final void transferFrom(List<T> source) { 118 assert source != null : "Violation of: source is not null"; 119 assert source != this : "Violation of: source is not this"; 120 assert source instanceof List2<?> 121 : "Violation of: source is of dynamic type List2<?>"; 122 /* 123 * This cast cannot fail since the assert above would have stopped 124 * execution in that case: source must be of dynamic type List2<?>, and 125 * the ? must be T or the call would not have compiled. 126 */ 127 List2<T> localSource = (List2<T>) source; 128 this.preStart = localSource.preStart; 129 this.lastLeft = localSource.lastLeft; 130 this.finish = localSource.finish; 131 this.rightLength = localSource.rightLength; 132 this.leftLength = localSource.leftLength; 133 localSource.createNewRep(); 134 } 135 136 @Override 137 public final void addRightFront(T x) { 138 assert x != null : "Violation of: x is not null"; 139 Node p = new Node(); 140 Node q = this.lastLeft; 141 p.data = x; 142 p.next = q.next; 143 q.next = p; 144 if (this.rightLength == 0) { 145 this.finish = p; 146 } 147 this.rightLength++; 148 } 149 150 @Override 151 public final T removeRightFront() { 152 assert this.rightLength() > 0 : "Violation of: this.right /= <>"; 153 Node p = this.lastLeft; 154 Node q = p.next; 155 p.next = q.next; 156 T x = q.data; 157 if (this.rightLength == 1) { 158 this.finish = this.lastLeft; 159 } 160 this.rightLength--; 161 return x; 162 } 163 164 @Override 165 public final void advance() { 166 assert this.rightLength() > 0 : "Violation of: this.right /= <>"; 167 Node p = this.lastLeft; 168 this.lastLeft = p.next; 169 this.leftLength++; 170 this.rightLength--; 171 } 172 173 @Override 174 public final void moveToStart() { 175 this.lastLeft = this.preStart; 176 this.rightLength += this.leftLength; 177 this.leftLength = 0; 178 } 179 180 @Override 181 public final int rightLength() { 182 return this.rightLength; 183 } 184 185 @Override 186 public final int leftLength() { 187 return this.leftLength; 188 } 189 190 @Override 191 public final Iterator<T> iterator() { 192 return new List2Iterator(); 193 } 194 195 /** 196 * Implementation of {@code Iterator} interface for {@code List2}. 197 */ 198 private final class List2Iterator implements Iterator<T> { 199 200 /** 201 * Current node in the linked list. 202 */ 203 private Node current; 204 205 /** 206 * No-argument constructor. 207 */ 208 private List2Iterator() { 209 this.current = List2.this.preStart.next; 210 } 211 212 @Override 213 public boolean hasNext() { 214 return this.current != null; 215 } 216 217 @Override 218 public T next() { 219 assert this.hasNext() : "Violation of: ~this.unseen /= <>"; 220 if (!this.hasNext()) { 221 /* 222 * Exception is supposed to be thrown in this case, but with 223 * assertion-checking enabled it cannot happen because of assert 224 * above. 225 */ 226 throw new NoSuchElementException(); 227 } 228 T x = this.current.data; 229 this.current = this.current.next; 230 return x; 231 } 232 233 @Override 234 public void remove() { 235 throw new UnsupportedOperationException("remove operation not supported"); 236 } 237 238 } 239 240 /* 241 * Other methods (overridden for performance reasons) --------------------- 242 */ 243 244 @Override 245 public final T rightFront() { 246 assert this.rightLength() > 0 : "Violation of: this.right /= <>"; 247 return this.lastLeft.next.data; 248 } 249 250 @Override 251 public final T replaceRightFront(T x) { 252 assert this.rightLength() > 0 : "Violation of: this.right /= <>"; 253 T rightFront = this.lastLeft.next.data; 254 this.lastLeft.next.data = x; 255 return rightFront; 256 } 257 258 @Override 259 public final void moveToFinish() { 260 this.lastLeft = this.finish; 261 this.leftLength += this.rightLength; 262 this.rightLength = 0; 263 } 264 265}