1+ /**
2+ * LinkedList class implements a doubly-linked list.
3+ */
4+ public class MyLinkedList <AnyType > implements Iterable <AnyType >
5+ {
6+ /**
7+ * Construct an empty LinkedList.
8+ */
9+ public MyLinkedList ( )
10+ {
11+ doClear ( );
12+ }
13+
14+ private void clear ( )
15+ {
16+ doClear ( );
17+ }
18+
19+ /**
20+ * Change the size of this collection to zero.
21+ */
22+ public void doClear ( )
23+ {
24+ beginMarker = new Node <>( null , null , null );
25+ endMarker = new Node <>( null , beginMarker , null );
26+ beginMarker .next = endMarker ;
27+
28+ theSize = 0 ;
29+ modCount ++;
30+ }
31+
32+ /**
33+ * Returns the number of items in this collection.
34+ * @return the number of items in this collection.
35+ */
36+ public int size ( )
37+ {
38+ return theSize ;
39+ }
40+
41+ public boolean isEmpty ( )
42+ {
43+ return size ( ) == 0 ;
44+ }
45+
46+ /**
47+ * Adds an item to this collection, at the end.
48+ * @param x any object.
49+ * @return true.
50+ */
51+ public boolean add ( AnyType x )
52+ {
53+ add ( size ( ), x );
54+ return true ;
55+ }
56+
57+ /**
58+ * Adds an item to this collection, at specified position.
59+ * Items at or after that position are slid one position higher.
60+ * @param x any object.
61+ * @param idx position to add at.
62+ * @throws IndexOutOfBoundsException if idx is not between 0 and size(), inclusive.
63+ */
64+ public void add ( int idx , AnyType x )
65+ {
66+ addBefore ( getNode ( idx , 0 , size ( ) ), x );
67+ }
68+
69+ /**
70+ * Adds an item to this collection, at specified position p.
71+ * Items at or after that position are slid one position higher.
72+ * @param p Node to add before.
73+ * @param x any object.
74+ * @throws IndexOutOfBoundsException if idx is not between 0 and size(), inclusive.
75+ */
76+ private void addBefore ( Node <AnyType > p , AnyType x )
77+ {
78+ Node <AnyType > newNode = new Node <>( x , p .prev , p );
79+ newNode .prev .next = newNode ;
80+ p .prev = newNode ;
81+ theSize ++;
82+ modCount ++;
83+ }
84+
85+
86+ /**
87+ * Returns the item at position idx.
88+ * @param idx the index to search in.
89+ * @throws IndexOutOfBoundsException if index is out of range.
90+ */
91+ public AnyType get ( int idx )
92+ {
93+ return getNode ( idx ).data ;
94+ }
95+
96+ /**
97+ * Changes the item at position idx.
98+ * @param idx the index to change.
99+ * @param newVal the new value.
100+ * @return the old value.
101+ * @throws IndexOutOfBoundsException if index is out of range.
102+ */
103+ public AnyType set ( int idx , AnyType newVal )
104+ {
105+ Node <AnyType > p = getNode ( idx );
106+ AnyType oldVal = p .data ;
107+
108+ p .data = newVal ;
109+ return oldVal ;
110+ }
111+
112+ /**
113+ * Gets the Node at position idx, which must range from 0 to size( ) - 1.
114+ * @param idx index to search at.
115+ * @return internal node corresponding to idx.
116+ * @throws IndexOutOfBoundsException if idx is not between 0 and size( ) - 1, inclusive.
117+ */
118+ private Node <AnyType > getNode ( int idx )
119+ {
120+ return getNode ( idx , 0 , size ( ) - 1 );
121+ }
122+
123+ /**
124+ * Gets the Node at position idx, which must range from lower to upper.
125+ * @param idx index to search at.
126+ * @param lower lowest valid index.
127+ * @param upper highest valid index.
128+ * @return internal node corresponding to idx.
129+ * @throws IndexOutOfBoundsException if idx is not between lower and upper, inclusive.
130+ */
131+ private Node <AnyType > getNode ( int idx , int lower , int upper )
132+ {
133+ Node <AnyType > p ;
134+
135+ if ( idx < lower || idx > upper )
136+ throw new IndexOutOfBoundsException ( "getNode index: " + idx + "; size: " + size ( ) );
137+
138+ if ( idx < size ( ) / 2 )
139+ {
140+ p = beginMarker .next ;
141+ for ( int i = 0 ; i < idx ; i ++ )
142+ p = p .next ;
143+ }
144+ else
145+ {
146+ p = endMarker ;
147+ for ( int i = size ( ); i > idx ; i -- )
148+ p = p .prev ;
149+ }
150+
151+ return p ;
152+ }
153+
154+ /**
155+ * Removes an item from this collection.
156+ * @param idx the index of the object.
157+ * @return the item was removed from the collection.
158+ */
159+ public AnyType remove ( int idx )
160+ {
161+ return remove ( getNode ( idx ) );
162+ }
163+
164+ /**
165+ * Removes the object contained in Node p.
166+ * @param p the Node containing the object.
167+ * @return the item was removed from the collection.
168+ */
169+ private AnyType remove ( Node <AnyType > p )
170+ {
171+ p .next .prev = p .prev ;
172+ p .prev .next = p .next ;
173+ theSize --;
174+ modCount ++;
175+
176+ return p .data ;
177+ }
178+
179+ /**
180+ * Returns a String representation of this collection.
181+ */
182+ public String toString ( )
183+ {
184+ StringBuilder sb = new StringBuilder ( "[ " );
185+
186+ for ( AnyType x : this )
187+ sb .append ( x + " " );
188+ sb .append ( "]" );
189+
190+ return new String ( sb );
191+ }
192+
193+ /**
194+ * Obtains an Iterator object used to traverse the collection.
195+ * @return an iterator positioned prior to the first element.
196+ */
197+ public java .util .Iterator <AnyType > iterator ( )
198+ {
199+ return new LinkedListIterator ( );
200+ }
201+
202+ /**
203+ * This is the implementation of the LinkedListIterator.
204+ * It maintains a notion of a current position and of
205+ * course the implicit reference to the MyLinkedList.
206+ */
207+ private class LinkedListIterator implements java .util .Iterator <AnyType >
208+ {
209+ private Node <AnyType > current = beginMarker .next ;
210+ private int expectedModCount = modCount ;
211+ private boolean okToRemove = false ;
212+
213+ public boolean hasNext ( )
214+ {
215+ return current != endMarker ;
216+ }
217+
218+ public AnyType next ( )
219+ {
220+ if ( modCount != expectedModCount )
221+ throw new java .util .ConcurrentModificationException ( );
222+ if ( !hasNext ( ) )
223+ throw new java .util .NoSuchElementException ( );
224+
225+ AnyType nextItem = current .data ;
226+ current = current .next ;
227+ okToRemove = true ;
228+ return nextItem ;
229+ }
230+
231+ public void remove ( )
232+ {
233+ if ( modCount != expectedModCount )
234+ throw new java .util .ConcurrentModificationException ( );
235+ if ( !okToRemove )
236+ throw new IllegalStateException ( );
237+
238+ MyLinkedList .this .remove ( current .prev );
239+ expectedModCount ++;
240+ okToRemove = false ;
241+ }
242+ }
243+
244+ /**
245+ * This is the doubly-linked list node.
246+ */
247+ private static class Node <AnyType >
248+ {
249+ public Node ( AnyType d , Node <AnyType > p , Node <AnyType > n )
250+ {
251+ data = d ; prev = p ; next = n ;
252+ }
253+
254+ public AnyType data ;
255+ public Node <AnyType > prev ;
256+ public Node <AnyType > next ;
257+ }
258+
259+ private int theSize ;
260+ private int modCount = 0 ;
261+ private Node <AnyType > beginMarker ;
262+ private Node <AnyType > endMarker ;
263+ }
264+
265+ class TestLinkedList
266+ {
267+ public static void main ( String [ ] args )
268+ {
269+ MyLinkedList <Integer > lst = new MyLinkedList <>( );
270+
271+ for ( int i = 0 ; i < 10 ; i ++ )
272+ lst .add ( i );
273+ for ( int i = 20 ; i < 30 ; i ++ )
274+ lst .add ( 0 , i );
275+
276+ lst .remove ( 0 );
277+ lst .remove ( lst .size ( ) - 1 );
278+
279+ System .out .println ( lst );
280+
281+ java .util .Iterator <Integer > itr = lst .iterator ( );
282+ while ( itr .hasNext ( ) )
283+ {
284+ itr .next ( );
285+ itr .remove ( );
286+ System .out .println ( lst );
287+ }
288+ }
289+ }
0 commit comments