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}