-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDoublyLinkedList.java
More file actions
314 lines (288 loc) · 7.5 KB
/
DoublyLinkedList.java
File metadata and controls
314 lines (288 loc) · 7.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/**
* A generic DoublyLinkedList implementation.
*
* @param <T> The type of elements contained in the DoublyLinkedList.
*
* @author karl88
* @author sfbahr
* @version Sep 17, 2014
*/
public class DoublyLinkedList<T>
{
//~ Instance/static variables .............................................
// A reference to the sentinel node at the beginning of the list.
private Node<T> head;
// A reference to the sentinel node at the end of the list.
private Node<T> tail;
// A reference to the current node in the list.
private Node<T> current;
// The number of elements in the list.
private int size;
//~ Constructor ...........................................................
// ----------------------------------------------------------
/**
* Construct the list.
*/
public DoublyLinkedList()
{
head = new Node<T>(null);
tail = new Node<T>(null);
current = null;
head.join(tail);
size = 0;
}
//~ Public methods ........................................................
// ----------------------------------------------------------
/**
* Gets the data from the current node in the list.
*
* @return the current data
*/
public T getCurrent()
{
if (current == null)
{
return null;
}
return current.data();
}
// ----------------------------------------------------------
/**
* Move current to the front of the list.
*/
public void moveToFront()
{
if (head.next() != tail)
{
current = head.next();
}
}
// ----------------------------------------------------------
/**
* Move current to the back of the list
*/
public void moveToBack()
{
if (tail.previous() != head)
{
current = tail.previous();
}
}
/**
* Moves through the list from front to back looking for a match. If there
* is none this is equivalent to moveToBack().
*
* Requires that class T supports the .equals(T) method.
*
* @param value the data value being checked
* @return true if successfully moved to a match, false if no match was
* found
*/
public boolean moveToValue(T value)
{
if (current == null)
{
return false;
}
moveToFront();
while (!current.data().equals(value))
{
if (!next())
{
return false;
}
}
return true;
}
/**
* Moves current to the next node in the list.
*
* @return true if current moved to the next value, false if it was
* already at the back or null.
*/
public boolean next()
{
if (current == null)
{
return false;
}
if (current.next() != tail)
{
current = current.next();
return true;
}
return false;
}
/**
* Moves current to the previous node in the list.
*
* @return true if current moved to the previous value, false if it was
* already at the front or null.
*/
public boolean previous()
{
if (current == null)
{
return false;
}
if (current.previous() != head)
{
current = current.previous();
return true;
}
return false;
}
/**
* If the list is currently empty, add the value to the list and make the
* added value the current value, otherwise simply add the new value after
* the current value.
*
* @param value the data value being inserted
* @return the correct node and value
*/
public DoublyLinkedList<T> insertAfterCurrent(T value)
{
if (current == null)
{
insert(head, new Node<T>(value));
current = head.next();
return this;
}
return insert(current, new Node<T>(value));
}
/**
* If the list is currently empty, add the value to the list and make the
* added value the current value, otherwise simply add the new value before
* the current value.
*
* @param value the data value being inserted
* @return the correct node and value
*/
public DoublyLinkedList<T> insertBeforeCurrent(T value)
{
if (current == null)
{
insert(head, new Node<T>(value));
current = head.next();
return this;
}
return insert(current.previous(), new Node<T>(value));
}
/**
* Handles the implementation of insertion for the two public insertion
* methods.
*
* @param first the node preceding the new node
* @param inserted the node being inserted
*/
private DoublyLinkedList<T> insert(Node<T> first, Node<T> inserted)
{
Node<T> oldSecond = first.next();
first.split();
first.join(inserted);
inserted.join(oldSecond);
size++;
return this;
}
// ----------------------------------------------------------
/**
* Remove the current node and move current to the next node.
*/
public void removeAndNext()
{
if (current == tail.previous() && size > 1)
{
removeAndPrevious();
return;
}
Node<T> removed = current;
next();
remove(removed);
}
// ----------------------------------------------------------
/**
* Remove the current node and move current to the previous node.
*/
public void removeAndPrevious()
{
if (current == head.next() && size > 1)
{
removeAndNext();
return;
}
Node<T> removed = current;
previous();
remove(removed);
}
/**
* Handles the implementation of removal for the two public remove
* methods.
*
* @param removed the node to be removed
*/
private void remove(Node<T> removed)
{
if (removed == null)
{
return;
}
Node<T> first = removed.previous();
Node<T> second = removed.next();
removed.split();
first.split();
first.join(second);
if (size == 1)
{
current = null;
}
size--;
}
/**
* Returns the size of the list.
*
* @return the size of the list
*/
public int getSize()
{
return size;
}
// ----------------------------------------------------------
/**
* Empties the list.
*/
public void clear()
{
if (size > 0)
{
tail.previous().split();
head.split();
head.join(tail);
}
size = 0;
}
/**
* Returns a string representation of this DoublyLinkedList in the following
* format:
* T1.toString() -> T2.toString() -> T3.toString()
*
* An empty list returns an empty string.
*
* @return the string representation of this DoublyLinkedList
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
Node<T> tempCurrent = head.next();
for (int i = 0; i < size; i++)
{
builder.append(tempCurrent.data().toString());
if (i < size - 1)
{
builder.append(" -> ");
}
tempCurrent = tempCurrent.next();
}
return builder.toString();
}
}