-
Notifications
You must be signed in to change notification settings - Fork 65
/
CustomBagLL.java
341 lines (314 loc) · 6.89 KB
/
CustomBagLL.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
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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/**
* Data-Structures-In-Java
* CustomBagLL.java
*/
package com.deepak.data.structures.Bag;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
/**
* Custom bag implementation using a Linked List
*
* @author Deepak
*
* @param <T>
*/
public class CustomBagLL<T> {
public static void main(String[] args) {
CustomBagLL<String> bag = new CustomBagLL<>();
System.out.println(bag.isEmpty());
bag.add("A");
bag.add("C");
bag.add("B");
bag.add("B");
bag.add("A");
bag.add("B");
System.out.println(bag.toString());
bag.remove("C");
System.out.println(bag.toString());
bag.remove("A");
System.out.println(bag.toString());
System.out.println("Bag contains C : " + bag.contains("C"));
System.out.println("Bag contains B : " + bag.contains("B"));
System.out.println("Bag Size : " + bag.size());
System.out.println("Bag Distinct Size : " + bag.distinctSize());
System.out.println("Grab : " + bag.grab());
Iterator<String> itr = bag.iterator();
/* Starting to print from iterator */
System.out.println();
System.out.println("Printing from iterator : ");
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
/* Head node */
private Node<T> head;
/**
* Constructor
*/
public CustomBagLL() {
this.head = null;
}
/**
* Method to add a item
*
* @param item
*/
public void add(T item) {
/* If bag is empty, make new item as head */
if (isEmpty()) {
Node<T> newNode = new Node<T>(item);
head = newNode;
} else {
/* Have two pointers current and last */
Node<T> current = head;
Node<T> last = head;
boolean found = false;
while (current != null) {
/* If that item is found, just increase the value */
if (current.item == item) {
current.incrementValue();
found = true;
break;
}
last = current;
current = current.next;
}
/* If not found, create as a new node and push to last */
if (!found) {
Node<T> newNode = new Node<T>(item);
last.next = newNode;
}
}
}
/**
* Method to remove a item
*
* @param item
* @return {@link boolean}
*/
public boolean remove(T item) {
/* If bag contains the item */
if (contains(item)) {
/* Have two pointers current and prev */
Node<T> current = head;
Node<T> prev = head;
/* Keep going while current is not null */
while (current != null) {
if (current.item == item) {
/* If item matches, check if it is a head or not */
if (current == head) {
/* If it's head, decrement the value and update head */
current.decrementValue();
if (current.value < 1) {
head = head.next;
}
return true;
} else {
/* Decrement the value, check if this was the last
* entry of that type, it yes, delete the item */
current.decrementValue();
if (current.value < 1) {
prev.next = current.next;
current.next = null;
}
return true;
}
}
/* Move to next set of items */
prev = current;
current = current.next;
}
}
return false;
}
/**
* Method to clear the bag
*/
public void clear() {
this.head = null;
}
/**
* Method to check if bag contains the item
*
* @param item
* @return {@link boolean}
*/
public boolean contains(T item) {
Node<T> current = head;
/* Start traversing and stop if item matches */
while (current != null) {
if (current.item == item) {
return true;
}
current = current.next;
}
return false;
}
/**
* Method to grab any random element
*
* @return {@link T}
*/
public T grab() {
/* Have a random index */
Random random = new Random();
int randomItemIndex = random.nextInt(distinctSize());
Node<T> current = head;
/* Move the pointer till we reach that random index */
for (int i = 0; i < randomItemIndex; i++) {
current = current.next;
}
return current.item;
}
/**
* Method to check size of the bag
*
* @return {@link int}
*/
public int size() {
Node<T> current = head;
int size = 0;
/* Keep traversing and track size of each entry */
while (current != null) {
size += current.value;
current = current.next;
}
return size;
}
/**
* Method to get distinct size of the bag
*
* @return {@link int}
*/
public int distinctSize() {
Node<T> current = head;
int counter = 0;
/* Increment the counter only when a new element is seen */
while (current != null) {
counter++;
current = current.next;
}
return counter;
}
/**
* Method to check if bag is empty
*
* @return {@link boolean}
*/
public boolean isEmpty() {
if (head == null) {
return true;
}
return false;
}
/**
* Method to print the content of bag as string
*/
public String toString() {
if (isEmpty()) {
return "Bag is Empty";
} else {
/* Keep appending the elements to string */
Node<T> current = head;
String str = "Bag = ";
while (current != null) {
for (int i = 0; i < current.value; i++) {
str += "{" + current.item + "}";
}
current = current.next;
}
return str;
}
}
/**
* Method to get a iterator on bag
*
* @return {@link Iterator<T>}
*/
public Iterator<T> iterator() {
return new Iterator<T>() {
/* Keep a track of next item and value count for each item */
private Node<T> nextItem = head;
private int valueCount = 0;
/**
* Method to check if bag has elements
*/
@Override
public boolean hasNext() {
/* If next item is head and it's not null,
* we have more elements */
if (nextItem == head && nextItem != null) {
return true;
} else if (nextItem != head && nextItem.next != null){
return true;
} else if (nextItem.value > valueCount + 1) {
return true;
}
return false;
}
/**
* Method to get the next element
*/
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException("No Element left in collection");
}
if (nextItem.value > valueCount) {
/* We still have items of same type left */
valueCount++;
} else {
/* Time to move to next item */
nextItem = nextItem.next;
valueCount = 0;
}
Node<T> itemToReturn = nextItem;
if (itemToReturn != null) {
return itemToReturn.item;
} else {
return null;
}
}
};
}
/**
* Class Node for Bag
*
* @author Deepak
*
* @param <E>
*/
public class Node<E> {
/* Item, counter associated with item and next pointer */
private E item;
private int value;
private Node<E> next;
/**
* Constructor to create the Node
*
* @param item
*/
public Node(E item) {
this.item = item;
this.value = 1;
this.next = null;
}
/**
* Method to increment the value
*/
public void incrementValue() {
value++;
}
/**
* Method to decrement the value
*/
public void decrementValue() {
value--;
}
@Override
public String toString() {
return "Item : [" + this.item + "]";
}
}
}