1
1
package me .ramswaroop .common ;
2
2
3
+ import java .util .NoSuchElementException ;
4
+
3
5
import static java .lang .System .out ;
4
6
5
7
/**
11
13
*/
12
14
public class DoubleLinkedList <E > implements LinkedList <E > {
13
15
14
- DoubleLinkedNode <E > head ;
16
+ public DoubleLinkedNode <E > head ;
17
+ public int size ;
15
18
16
19
@ Override
17
20
public boolean add (E item ) {
18
- return false ;
21
+ DoubleLinkedNode <E > newNode = new DoubleLinkedNode <>(null , item , null );
22
+ if (head == null ) { // list empty
23
+ head = newNode ;
24
+ } else { // add to the end of list
25
+ DoubleLinkedNode <E > curr = head ;
26
+ while (curr .next != null ) {
27
+ curr = curr .next ;
28
+ }
29
+ curr .next = newNode ;
30
+ newNode .prev = curr ;
31
+ }
32
+ size ++;
33
+ return true ;
19
34
}
20
35
21
36
@ Override
22
37
public boolean add (int index , E item ) {
23
- return false ;
38
+ isIndexOutOfBounds (index );
39
+
40
+ if (index == 0 ) { // add at first
41
+ addFirst (item );
42
+ } else { // add at any other location
43
+ DoubleLinkedNode <E > prevNode = getPredecessorNode (index );
44
+ DoubleLinkedNode <E > nextNode = prevNode .next ;
45
+ DoubleLinkedNode <E > newNode = new DoubleLinkedNode <>(prevNode , item , prevNode .next );
46
+ prevNode .next = newNode ;
47
+ if (nextNode != null ) nextNode .prev = newNode ;
48
+ size ++;
49
+ }
50
+ return true ;
24
51
}
25
52
26
53
@ Override
27
54
public void addFirst (E item ) {
28
-
55
+ DoubleLinkedNode <E > newNode = new DoubleLinkedNode <>(null , item , head );
56
+ if (head != null ) head .prev = newNode ;
57
+ head = newNode ;
58
+ size ++;
29
59
}
30
60
31
61
@ Override
32
62
public void addLast (E item ) {
33
-
63
+ add ( item );
34
64
}
35
65
36
66
@ Override
37
67
public void clear () {
38
-
68
+ // Clearing all of the links between nodes is "unnecessary", but:
69
+ // - helps a generational GC if the discarded nodes inhabit
70
+ // more than one generation
71
+ // - is sure to free memory even if there is a reachable Iterator
72
+ for (DoubleLinkedNode <E > node = head ; node != null ; ) {
73
+ DoubleLinkedNode <E > next = node .next ;
74
+ node .item = null ;
75
+ node .next = null ;
76
+ node .prev = null ;
77
+ node = next ;
78
+ }
79
+ head = null ;
80
+ size = 0 ;
39
81
}
40
82
41
83
@ Override
@@ -45,47 +87,90 @@ public LinkedList<E> clone() {
45
87
46
88
@ Override
47
89
public boolean contains (E item ) {
48
- return false ;
90
+ return getNode ( item ) != null ;
49
91
}
50
92
51
93
@ Override
52
94
public E get (int index ) {
53
- return null ;
95
+ return getNode ( index ). item ;
54
96
}
55
97
56
98
@ Override
57
99
public E getFirst () {
58
- return null ;
100
+ isLinkedListEmpty ();
101
+ return head .item ;
59
102
}
60
103
61
104
@ Override
62
105
public E getLast () {
63
- return null ;
106
+ return getNode ( size - 1 ). item ;
64
107
}
65
108
66
109
@ Override
67
110
public E remove () {
68
- return null ;
111
+ isLinkedListEmpty ();
112
+
113
+ E item = head .item ;
114
+ head = head .next ;
115
+ if (head != null ) head .prev = null ; // check for linked list size = 1
116
+ size --;
117
+ return item ;
69
118
}
70
119
71
120
@ Override
72
121
public E remove (int index ) {
73
- return null ;
122
+ isLinkedListEmpty ();
123
+
124
+ DoubleLinkedNode <E > prevNode = getPredecessorNode (index );
125
+ DoubleLinkedNode <E > nextNode ;
126
+ DoubleLinkedNode <E > delNode ;
127
+ if (prevNode == null ) { // index = 0
128
+ delNode = head ;
129
+ head = head .next ;
130
+ if (head != null ) head .prev = null ; // check for linked list size = 1
131
+ size --;
132
+ return delNode .item ;
133
+ } else {
134
+ delNode = prevNode .next ;
135
+ nextNode = delNode .next ;
136
+ prevNode .next = nextNode ;
137
+ if (nextNode != null ) nextNode .prev = prevNode ; // check needed if node to be deleted is last node
138
+ size --;
139
+ return delNode .item ;
140
+ }
74
141
}
75
142
76
143
@ Override
77
144
public boolean removeItem (E item ) {
78
- return false ;
145
+ isLinkedListEmpty ();
146
+
147
+ if (!contains (item )) return false ;
148
+
149
+ DoubleLinkedNode <E > prevNode = getPredecessorNode (item );
150
+ DoubleLinkedNode <E > nextNode ;
151
+ if (prevNode == null ) { // index = 0
152
+ head = head .next ;
153
+ if (head != null ) head .prev = null ; // condition for list size = 1
154
+ size --;
155
+ } else {
156
+ nextNode = prevNode .next .next ;
157
+ prevNode .next = nextNode ;
158
+ if (nextNode != null ) nextNode .prev = prevNode ;
159
+ size --;
160
+ }
161
+ return true ;
79
162
}
80
163
81
164
@ Override
82
165
public E set (int index , E item ) {
83
- return null ;
166
+ DoubleLinkedNode <E > node = getNode (index );
167
+ node .item = item ;
168
+ return node .item ;
84
169
}
85
170
86
171
@ Override
87
172
public int size () {
88
- return 0 ;
173
+ return size ;
89
174
}
90
175
91
176
@ Override
@@ -96,10 +181,70 @@ public void printList() {
96
181
out .println ("]" );
97
182
return ;
98
183
}
184
+ // prints the list from first node
99
185
while (curr .next != null ) {
100
186
out .print (curr .item + "," );
101
187
curr = curr .next ;
102
188
}
103
189
out .println (curr .item + "]" );
190
+ // prints the list from last node
191
+ out .print ("[" );
192
+ while (curr .prev != null ) {
193
+ out .print (curr .item + "," );
194
+ curr = curr .prev ;
195
+ }
196
+ out .println (curr .item + "]" );
197
+ }
198
+
199
+ private DoubleLinkedNode <E > getPredecessorNode (int index ) {
200
+ return index > 0 ? getNode (index - 1 ) : null ;
201
+ }
202
+
203
+ private DoubleLinkedNode <E > getPredecessorNode (E item ) {
204
+ return getNode (item ) != null ? getNode (item ).prev : null ;
205
+ }
206
+
207
+ protected DoubleLinkedNode <E > getNode (int index ) {
208
+ isIndexOutOfBounds (index );
209
+
210
+ DoubleLinkedNode <E > curr = head ;
211
+ int i = 0 ;
212
+ while (i < index ) {
213
+ curr = curr .next ;
214
+ i ++;
215
+ }
216
+ return curr ;
217
+ }
218
+
219
+ protected DoubleLinkedNode <E > getNode (E item ) {
220
+ DoubleLinkedNode <E > curr = head ;
221
+ if (item == null ) {
222
+ while (curr != null ) { // when item is null, use == rather than equals()
223
+ if (curr .item == item ) {
224
+ return curr ;
225
+ }
226
+ curr = curr .next ;
227
+ }
228
+ } else {
229
+ while (curr != null ) {
230
+ if (curr .item .equals (item )) {
231
+ return curr ;
232
+ }
233
+ curr = curr .next ;
234
+ }
235
+ }
236
+ return null ;
237
+ }
238
+
239
+ private void isLinkedListEmpty () {
240
+ if (head == null ) {
241
+ throw new NoSuchElementException ("LinkedList empty" );
242
+ }
243
+ }
244
+
245
+ private void isIndexOutOfBounds (int index ) {
246
+ if (index < 0 || index > size ) {
247
+ throw new IndexOutOfBoundsException ("Index [" + index + "] must be less than size [" + size + "]" );
248
+ }
104
249
}
105
250
}
0 commit comments