@@ -40,7 +40,7 @@ public LinkedList(Node<T> head) {
40
40
this .head = head ;
41
41
Node <T > trav = head ;
42
42
int count = 0 ;
43
- while (trav != null ) {
43
+ while (trav != null ) { // We count the size of our linked list through iteration.
44
44
count ++;
45
45
trav = trav .next ;
46
46
}
@@ -60,24 +60,6 @@ public int size() {
60
60
return this .size ;
61
61
}
62
62
63
- /**
64
- * Inserts the object at the front of the linked list
65
- * @param object to be inserted
66
- * @return boolean representing whether insertion was successful
67
- */
68
- public boolean insertFront (T object ) {
69
- return insert (object , 0 );
70
- }
71
-
72
- /**
73
- * Inserts the object at the end of the linked list
74
- * @param object to be inserted
75
- * @return boolean representing whether insertion was successful
76
- */
77
- public boolean insertEnd (T object ) {
78
- return insert (object , this .size );
79
- }
80
-
81
63
/**
82
64
* inserts the object at the specified index of the linked list
83
65
* @param object to be inserted
@@ -92,7 +74,7 @@ public boolean insert(T object, int idx) {
92
74
93
75
Node <T > newNode = new Node <>(object );
94
76
95
- if (head == null ) {
77
+ if (head == null ) { // Linked list empty; We just need to add the head;
96
78
head = newNode ;
97
79
size ++;
98
80
return true ;
@@ -105,7 +87,7 @@ public boolean insert(T object, int idx) {
105
87
trav = trav .next ;
106
88
}
107
89
108
- if (prev != null ) {
90
+ if (prev != null ) { // Reset the pointer at the index.
109
91
prev .next = newNode ;
110
92
newNode .next = trav ;
111
93
} else { // case when inserting at index 0; need to update head
@@ -116,6 +98,24 @@ public boolean insert(T object, int idx) {
116
98
return true ;
117
99
}
118
100
101
+ /**
102
+ * Inserts the object at the front of the linked list
103
+ * @param object to be inserted
104
+ * @return boolean representing whether insertion was successful
105
+ */
106
+ public boolean insertFront (T object ) {
107
+ return insert (object , 0 );
108
+ }
109
+
110
+ /**
111
+ * Inserts the object at the end of the linked list
112
+ * @param object to be inserted
113
+ * @return boolean representing whether insertion was successful
114
+ */
115
+ public boolean insertEnd (T object ) {
116
+ return insert (object , this .size );
117
+ }
118
+
119
119
/**
120
120
* remove the node at the specified index
121
121
* @param idx of the node to be removed
@@ -133,7 +133,7 @@ public T remove(int idx) {
133
133
for (int i = 0 ; i < idx ; i ++) {
134
134
prev = trav ;
135
135
trav = trav .next ;
136
- }
136
+ } // This iteration allows us to store a copy of nodes before and after idx.
137
137
138
138
if (prev != null ) {
139
139
prev .next = trav .next ;
@@ -144,15 +144,38 @@ public T remove(int idx) {
144
144
return trav .val ;
145
145
}
146
146
147
+ /**
148
+ * search for the 1st encounter of the node that holds the specified object
149
+ * @param object
150
+ * @return index of the node found
151
+ */
152
+ public int search (T object ) {
153
+ Node <T > trav = head ;
154
+ int idx = 0 ;
155
+ if (trav == null ) { // Empty linked list.
156
+ return -1 ;
157
+ }
158
+
159
+ while (trav != null ) {
160
+ if (trav .val .equals (object )) {
161
+ return idx ;
162
+ }
163
+ idx ++;
164
+ trav = trav .next ;
165
+ }
166
+
167
+ return -1 ;
168
+ }
169
+
147
170
/**
148
171
* delete the 1st encounter of the specified object from the linked list
149
172
* @param object to search and delete
150
173
* @return boolean whether the delete op was successful
151
174
*/
152
175
public boolean delete (T object ) {
153
- int idx = search (object );
176
+ int idx = search (object ); // Get index of object to remove.
154
177
if (idx != -1 ) {
155
- remove (idx );
178
+ remove (idx ); // Remove based on that index.
156
179
return true ;
157
180
}
158
181
return false ;
@@ -174,28 +197,6 @@ public T poll() {
174
197
return remove (0 );
175
198
}
176
199
177
- /**
178
- * search for the 1st encounter of the node that holds the specified object
179
- * @param object
180
- * @return index of the node found
181
- */
182
- public int search (T object ) {
183
- Node <T > trav = head ;
184
- int idx = 0 ;
185
- if (trav == null ) {
186
- return -1 ;
187
- }
188
-
189
- while (trav != null ) {
190
- if (trav .val .equals (object )) {
191
- return idx ;
192
- }
193
- idx ++;
194
- trav = trav .next ;
195
- }
196
-
197
- return -1 ;
198
- }
199
200
200
201
/**
201
202
* get the node at the specified index
@@ -204,7 +205,7 @@ public int search(T object) {
204
205
*/
205
206
public Node <T > get (int idx ) {
206
207
Node <T > trav = head ;
207
- if (idx < this .size && trav != null ) {
208
+ if (idx < this .size && trav != null ) { // Check: idx is valid & linked list not empty.
208
209
for (int i = 0 ; i < idx ; i ++) {
209
210
trav = trav .next ;
210
211
}
@@ -214,29 +215,38 @@ public Node<T> get(int idx) {
214
215
}
215
216
216
217
/**
217
- * reverse the linked list
218
+ * reverse the linked list.
219
+ * A good video to visualise this algorithm can be found
220
+ * <a = https://www.youtube.com/watch?v=D7y_hoT_YZI, href = "url">here</a>.
218
221
*/
219
222
public void reverse () {
220
- if (head == null || head .next == null ) {
223
+ if (head == null || head .next == null ) { // No need to reverse if list is empty or only 1 element.
221
224
return ;
222
225
}
223
226
224
227
Node <T > prev = head ;
225
228
Node <T > curr = head .next ;
226
- Node <T > newHead = curr ;
227
- prev .next = null ;
229
+ Node <T > newHead = curr ; // Store the next head.
230
+ prev .next = null ; // Reset to null, representing end of list.
228
231
while (curr .next != null ) {
229
- newHead = curr .next ;
230
- curr .next = prev ;
232
+ newHead = curr .next ; // We set the next element as the newHead.
233
+ curr .next = prev ; // Replace our current node as the previous node.
231
234
prev = curr ;
232
- curr = newHead ;
235
+ curr = newHead ; // Set our current node as the next element (newHead) to look at.
233
236
}
234
237
newHead .next = prev ;
235
- head = newHead ;
238
+ head = newHead ; // newHead is last ele from org. list -> First ele of our reversed list.
236
239
}
237
240
238
241
/**
239
- * sorts the linked list by their natural order
242
+ * Sorts the linked list by the natural order of the elements.
243
+ * Generally, merge sort is the most efficient sorting algorithm for linked lists.
244
+ * Addressing a random node in the linked list incurrs O(n) time complexity.
245
+ * This makes sort algorithms like quicksort and heapsort inefficient since they rely
246
+ * on the O(1) lookup time of an array.
247
+ *
248
+ * A good video to visualise this algorithm can be found
249
+ * <a = https://www.youtube.com/watch?v=JSceec-wEyw, href = "url">here</a>.
240
250
*/
241
251
public void sort () {
242
252
if (this .size <= 1 ) {
@@ -245,11 +255,11 @@ public void sort() {
245
255
int mid = (this .size - 1 ) / 2 ;
246
256
Node <T > middle = this .get (mid );
247
257
Node <T > nextHead = middle .next ;
248
- LinkedList <T > next = new LinkedList <>(nextHead , this .size - 1 - mid );
258
+ LinkedList <T > next = new LinkedList <>(nextHead , this .size - 1 - mid ); // Split the list into 2.
249
259
middle .next = null ;
250
- this .size = mid + 1 ; // update size of original LL after split
260
+ this .size = mid + 1 ; // update size of original list after split
251
261
252
- next .sort ();
262
+ next .sort (); // Recursively sort the list.
253
263
this .sort ();
254
264
head = merge (this , next );
255
265
}
@@ -268,6 +278,7 @@ private Node<T> merge(LinkedList<T> first, LinkedList<T> second) {
268
278
269
279
while (headFirst != null && headSecond != null ) {
270
280
if (headFirst .val .compareTo (headSecond .val ) < 0 ) {
281
+ // Note that first & second either only have 2 values or are already sorted.
271
282
trav .next = headFirst ;
272
283
headFirst = headFirst .next ;
273
284
} else {
@@ -277,10 +288,9 @@ private Node<T> merge(LinkedList<T> first, LinkedList<T> second) {
277
288
trav = trav .next ;
278
289
}
279
290
280
- if (headFirst != null ) {
291
+ if (headFirst != null ) { // Add any remaining nodes from first.
281
292
trav .next = headFirst ;
282
- }
283
- if (headSecond != null ) {
293
+ } else { // We know loop terminated because of second; Add any remaining nodes from second.
284
294
trav .next = headSecond ;
285
295
}
286
296
return dummy .next ;
0 commit comments