-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCircularLinkedList.java
More file actions
324 lines (302 loc) · 9.06 KB
/
CircularLinkedList.java
File metadata and controls
324 lines (302 loc) · 9.06 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
315
316
317
318
319
320
321
322
323
324
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Represents an expanded LinkedList that is circular (last element points to first)
* @param <E> Data type of elements to be stored in the CircularLinkedList
*/
public class CircularLinkedList<E> implements CircularLinkedListInterface<E>, Iterable<E> {
/**
* Front of the list, null if empty, or refers to an element
*/
private Node<E> front;
/**
* End of the list, null if empty, or refers to an element
*/
private Node<E> end;
/**
* Number of elements in the list
*/
private int size;
/**
* Constructs new empty CircularLinkedList
*/
public CircularLinkedList() {
clear();
}
/**
* Clears the list, emptying it of all elements.
*/
public void clear() {
front = null;
end = null;
size = 0;
}
/**
* Retrieves a count of elements being maintained by the list.
*
* @return the size of the list (count of elements)
*/
@Override
public int getSize() {
return size;
}
/**
* Retrieves the data at the specified position in the list
*
* @param position 0-based index for the list; must be in the range 0 to size - 1
* @return the data in the specified position in the list
*/
@Override
public E get(int position) {
return getNode(position).data;
}
/**
* Retrieves the Node at the specified position in the list
* @param position 0 based index for the list; must be in the range 0 to size - 1
* @return the Node at the specified position in the list
*/
private Node<E> getNode(int position) {
if (position < 0 || position >= size) {
throw new IndexOutOfBoundsException("position must be in range 0 to size - 1");
}
Node<E> current = front;
for (int currentPos = 1; currentPos <= position; currentPos++) {
current = current.next;
}
return current;
}
/**
* Adds a new node to the front of the list
* @param data value to add to the list
*/
public void addAtFront(E data) {
Node<E> newNode = new Node<>(data, front);
if (front == null) {
newNode.next = newNode;
end = newNode;
} else {
end.next = newNode;
}
front = newNode;
size++;
}
/**
* Adds a new node to the end of the list; by nature, this element's next will point to the first element
*
* @param data value to add to the list
*/
@Override
public void add(E data) {
Node<E> newNode = new Node<>(data, front);
if (front == null) {
addAtFront(data);
} else {
end.next = newNode;
end = newNode;
size++;
}
}
/**
* Adds a second list to the end of the current list
* @param listToAdd list to be added
*/
public void addListToList(CircularLinkedList<E> listToAdd) {
if (front == null) {
front = listToAdd.front;
end = listToAdd.end;
} else {
end.next = listToAdd.front;
end = listToAdd.end;
listToAdd.end.next = front;
}
size += listToAdd.getSize();
}
/**
* Returns the index of the first instance of the value
* @param value data value to look for
* @return the index of the value, or -1 if not found
*/
public int indexOf(E value) {
if (front == null) {
return -1;
}
Node<E> current = front;
int position = 0;
if (current.data == value) {
return position;
}
while (current.next != front) {
position++;
current = current.next;
if (current.data == value) {
return position;
}
}
return -1;
}
// /**
// * Returns a reference to the first Node with the value
// * @param value data value to look for
// * @return a reference to the first Node with that value, or null if not found
// */
// private Node<E> nodeOf(E value) {
// if (front == null) {
// return null;
// }
// Node<E> current = front;
// if (current.data == value) {
// return current;
// }
// while (current.next != front) {
// current = current.next;
// if (current.data == value) {
// return current;
// }
// }
// return null;
// }
/**
* Removes the specified item from the list, if it exists there.
*
* @param value the element to remove from the list
* @return true, if the element was found and removed; false, if not found or list is empty
*/
@Override
public boolean remove(E value) {
int pos = indexOf(value);
if (pos == -1) {
return false;
} else {
remove(pos);
return true;
}
}
/**
* Removes the node at the specified position in the list
*
* @param position position in the list; must be in range 0 to size - 1
*/
@Override
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IndexOutOfBoundsException("position must be in range 0 to size - 1");
}
if (position == 0) {
front = front.next;
size--;
return;
}
Node<E> current = front;
for (int pos = 1; pos < position; pos++) {
current = current.next;
}
if (position == size - 1) {
end = current.next.next;
}
current.next = current.next.next;
size--;
}
/**
* Returns a String representation of the list
* @return String of all the elements in the list
*/
@Override
public String toString() {
if (size == 0) {
return "[]";
} else {
String rep = "[" + front.data;
Node<E> current = front.next;
while (current != front) {
rep += ", " + current.data;
current = current.next;
}
rep += "]";
return rep;
}
}
/**
* Retrieves an iterator over the list's elements. Do not do other list operations like add or remove
* from within an iterator loop; the results are not guaranteed to function as you might expect
* @return a strongly typed iterator over elements in the list
*/
@Override
public Iterator<E> iterator() {
return new CircularLinkedListIterator();
}
/**
* Iterator for the CircularLinkedList
*/
private class CircularLinkedListIterator implements Iterator<E> {
/**
* Current node being referenced by the iterator
*/
public Node<E> current;
/**
* Constructor
*/
public CircularLinkedListIterator() {
current = null;
}
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
@Override
public boolean hasNext() {
return size != 0;
}
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
} else {
if (current == null) {
current = front;
} else {
current = current.next;
}
return current.data;
}
}
}
/**
* Container for element data
* @param <T> Data type of element data to be stored
*/
private static class Node<T> {
/**
* the data to be added to the list
*/
public T data;
/**
* node that this node should connect to
*/
public Node<T> next;
//basic constructors, did not use
// public Node() {
// this(null, null);
// }
// public Node(T data) {
// this(data, null);
// }
/**
* Constructor
* @param data the data to be added to the list
* @param next node that this node should connect to
*/
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
}
}