-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathIntNode.java
290 lines (231 loc) · 11 KB
/
IntNode.java
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
/**
* Created by jkeys on 9/13/2015.
*/
public class IntNode {
/* private member variables */
private int data; //the data to be stored (integer)
private IntNode next; //ref to next node in list
/* standard constructors */
public IntNode() {
data = 0;
next = null;
}
public IntNode(int _data, IntNode _node) {
data = _data;
next = _node;
}
/* standard getters and setters */
public void setData(int _data) {
data = _data;
}
public void setNext(IntNode _next) {
next = _next;
}
public int getData() {
return data;
}
public IntNode getNext() {
return next;
}
public String toString() {
IntNode rover = this; //use a roving reference var to walk over list; make it start at the current object
StringBuilder sb = new StringBuilder(); //stringbuilder to efficiently append result string
//use while loop to walk over list, until reaching a null reference (i.e. the end of the list)
while (rover != null) {
sb.append("(" + rover.data + ")"); //append the data
if (rover.next != null) //if we're not at the end, append an arrow too
sb.append("--->");
rover = rover.next; //then look at the next node in the list (if null, loop does not execute again)
}
return sb.toString(); //return string representation of StringBuilder
}
/**
* @param newdata The data to be inserted into the newly created node.
*/
public void addNodeAfterThis(int newdata) {
IntNode newNode = new IntNode(newdata, this.next); //create the new node, give it the correct link (this.next)
this.next = newNode; //then replace the current this.next with a ref to the newNode.
}
/**
* @param head The head of the list. (Each node is a list unto itself.)
* @return count The number of nodes in the list.
*/
public static int listLength(IntNode head) {
if (head == null) //check precondition
return 0;
//counter variable and rover to wlak over list
int count = 0;
IntNode rover = head;
//walk over list using while loop
while (rover != null) {
count++; //add one each time you look at a node
rover = rover.next; //then look at the next node
}
return count; //return the number of nodes
}
/**
* @param head The first node in the list
* @param data The data to be searched for
* @return true if the list contains element equal to "data"; false otherwise
*/
public static boolean search(IntNode head, int data) {
if (head == null) //check precondition
return false;
IntNode rover = head; //rover reference to walk over list
while (rover != null) {
if (data == rover.getData()) { //if data is equal, return true
return true;
}
rover = rover.next; //look at next node (might be null)
}
return false; //if reach end of list w/o finding, return false (unfound)
}
public void removeNodeAfterThis() {
IntNode newNext = this.next.getNext();
this.next.setNext(null); //unlink the removed node's next (make it null)
this.next = newNext; //remove reference to removed node, let garbage collector do its thing
}
/**
* @param n The number to be checked for odd parity
* @return True if n is odd, false otherwise.
*/
private static boolean isOdd(int n) {
return n % 2 != 0; //a number is odd if it has a remainder other than 0 when divided by 2; therefore use modulo
}
/**
* @param head The head of the list
* @return The count of odd numbers in the list
*/
public static int listOddNumber(IntNode head) {
if(head == null) //check precondition
return 0;
int count = 0; //counting var
IntNode rover = head; //rover reference to walk over list
while(rover != null) { //walk over list until you hit null (past the end)
if(isOdd(rover.data)) { //check if the current element's data is odd
count++; //and count it if so
}
rover = rover.getNext(); //and move to the next element in the list.
}
return count; //return the count of odd numbers
}
public void addToEnd(int newdata) {
IntNode rover = this; //rover reference to walk over list
while(rover.getNext() != null) { //walk until
rover = rover.getNext(); //walk over until you hit the tail element (until rover.getNext() == null)
}
IntNode newNode = new IntNode(newdata, null); //create the new node and give it the newdata
rover.setNext(newNode); //and link it up to rover's next
}
//recursive solution b/c why not
private static int sumLastRecurHelper(IntNode head, int numLeft) {
if(numLeft == 0 || head == null) //base case
return 0; //return 0; this anchors the sum, so you eventually get like 1 + 2 + 3 + 4 + 0
else //otherwise, return the current node's data plus the sum of its sublist. (Eventually sum of sublist == 0; base case.)
return head.getData() + sumLastRecurHelper(head.getNext(), numLeft - 1);
}
//this method makes the sumLast method a lot simpler
private int size() {
int count = 0;
IntNode rover = this;
while(rover != null) {
count++;
rover = rover.getNext();
}
return count;
}
public static int sumLast(IntNode head, int num) {
if(head == null || num <= 0)
return 0;
IntNode rover = head;
//walk over as many elements need to be ignored (size - num); if list of size 10 and num of 6,
//you want to ignore the first 10-6=4 elements. So walk over four times, then recursively calculate the list.
for (int i = 0; i < head.size() - num; i++) {
if(rover.getNext() != null) {
rover = rover.getNext(); //move to next node
}
else {
break; //break to avoid null dereference (is this a segfault in Java? NULL->method() is a segfault in C++.)
}
}
return sumLastRecurHelper(rover, num); //then let the recursive helper method do the actual summation.
}
/**
* @param head The head of the list.
* @return The new head of the copied list.
*/
public static IntNode copyOdd(IntNode head) {
if(head == null)
return null;
IntNode rover = head; //rover reference to walk over list
IntNode newHead = null; //this will hold the new head
IntNode newRover = newHead; //and this will be the rover to walk over the new list once the new head has been created
//walk over the list
while(rover != null) {
if(isOdd(rover.getData())) { //check if the current node of the list to be copied is odd
if (newHead == null) { //if we havent' already created the new list
newHead = new IntNode(rover.getData(), null); //then create the newHead IntNode object
newRover = newHead; //and start the rover equal to its reference
} else { //else the new list has been created
newRover.addNodeAfterThis(rover.getData()); //so just add the new node
newRover = newRover.getNext(); //and move its rover down one
}
}
rover = rover.getNext(); //and walk down the initial list again; this happens regardless of whether rover is odd
}
return newHead; //can be null if no odd elements
}
/**
* @param head The head of the list.
* @param e The element to be found and removed.
* @return The new head of the list.
*/
public static IntNode removeFirst(IntNode head, int e) {
if(head == null) { //check precondition
return null;
}
IntNode rover = head; //rover reference to walk over list
IntNode roverNext = rover.getNext(); //and the next elem in the list
//check case where e == head.data
if (rover.getData() == e) {
head.setNext(null); //unlink the head (it is being removed)
return roverNext; //and return the newHead (the second element in the list)
}
if(roverNext == null) //if roverNext == null and head.data != e, then return the 1-node list
return head;
//otherwise, walk over the list until we find one
do {
if(roverNext != null && roverNext.getData() == e) { //check if roverNext's data is equal to e
rover.removeNodeAfterThis(); //if it is, remove roverNext (by calling removeNodeAfterThis on rover)
break; //and break out of the loop
}
rover = roverNext; //inchworm the rover down
if(rover != null) //and if it did not inchworm to the end,
roverNext = rover.getNext(); //then set roverNext equal to next node.
} while(rover != null); //go until we hit null (past tail of list).
return head; //return the head; we already checked case where head.data == e, so if we get this far, we guarantee the original head is the new head.
}
//this is a lazy method that just calls removeFirst repeatedly until nothing is removed.
public static IntNode removeAll(IntNode head, int e) {
int currentSize = head.size(); //keep track of the list's current size
//lazy loop condition
while(true) {
IntNode newHead = IntNode.removeFirst(head, e); //remove the first element equal to e and store the newHead
if(newHead.size() == currentSize) //if the newHead size equals the original (or if already removed, current) size, nothing removed:
return newHead; //so return the newHead. (If nothing removed at all, newHead == head)
else
currentSize = newHead.size(); //otherwise, sizes no longer match, a node was removed. Store the new size and do it again.
}
}
public static IntNode reverse(IntNode head) {
IntNode reversed = null; //store a reference to the reversed bit of the list; so far we haven't reversed anything, so null. Could also be called "newHead"
IntNode rover = head; //and start with the current node at the head of the list.
while (rover != null) { //go until we have reversed every node
IntNode roverNext = rover.getNext(); //So store the next element after the current node
rover.setNext(reversed); //then, reverse the current node by making its next point in the opposite direction; initially this is null (because the head becomes the tail, and tail.next == null)
reversed = rover; //make the reversed sublist point to the node that was just reversed
rover = roverNext; //and walk the rover down one more node.
}
return reversed; //and finally, return the now fully reversed list.
}
}