1
+ /**
2
+ * Data-Structures-In-Java
3
+ * CustomBagLL.java
4
+ */
5
+ package com .deepak .data .structures .Bag ;
6
+
7
+ import java .util .Iterator ;
8
+ import java .util .NoSuchElementException ;
9
+ import java .util .Random ;
10
+
11
+ /**
12
+ * Custom bag implementation using a Linked List
13
+ *
14
+ * @author Deepak
15
+ *
16
+ * @param <T>
17
+ */
18
+ public class CustomBagLL <T > {
19
+
20
+ public static void main (String [] args ) {
21
+ CustomBagLL <String > bag = new CustomBagLL <>();
22
+ System .out .println (bag .isEmpty ());
23
+ bag .add ("A" );
24
+ bag .add ("C" );
25
+ bag .add ("B" );
26
+ bag .add ("B" );
27
+ bag .add ("A" );
28
+ bag .add ("B" );
29
+ System .out .println (bag .toString ());
30
+ bag .remove ("C" );
31
+ System .out .println (bag .toString ());
32
+ bag .remove ("A" );
33
+ System .out .println (bag .toString ());
34
+ System .out .println ("Bag contains C : " + bag .contains ("C" ));
35
+ System .out .println ("Bag contains B : " + bag .contains ("B" ));
36
+ System .out .println ("Bag Size : " + bag .size ());
37
+ System .out .println ("Bag Distinct Size : " + bag .distinctSize ());
38
+ System .out .println ("Grab : " + bag .grab ());
39
+ Iterator <String > itr = bag .iterator ();
40
+ /* Starting to print from iterator */
41
+ System .out .println ();
42
+ System .out .println ("Printing from iterator : " );
43
+ while (itr .hasNext ()) {
44
+ System .out .println (itr .next ());
45
+ }
46
+ }
47
+
48
+ /* Head node */
49
+ private Node <T > head ;
50
+
51
+ /**
52
+ * Constructor
53
+ */
54
+ public CustomBagLL () {
55
+ this .head = null ;
56
+ }
57
+
58
+ /**
59
+ * Method to add a item
60
+ *
61
+ * @param item
62
+ */
63
+ public void add (T item ) {
64
+ /* If bag is empty, make new item as head */
65
+ if (isEmpty ()) {
66
+ Node <T > newNode = new Node <T >(item );
67
+ head = newNode ;
68
+ } else {
69
+ /* Have two pointers current and last */
70
+ Node <T > current = head ;
71
+ Node <T > last = head ;
72
+ boolean found = false ;
73
+ while (current != null ) {
74
+ /* If that item is found, just increase the value */
75
+ if (current .item == item ) {
76
+ current .incrementValue ();
77
+ found = true ;
78
+ break ;
79
+ }
80
+ last = current ;
81
+ current = current .next ;
82
+ }
83
+ /* If not found, create as a new node and push to last */
84
+ if (!found ) {
85
+ Node <T > newNode = new Node <T >(item );
86
+ last .next = newNode ;
87
+ }
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Method to remove a item
93
+ *
94
+ * @param item
95
+ * @return {@link boolean}
96
+ */
97
+ public boolean remove (T item ) {
98
+ /* If bag contains the item */
99
+ if (contains (item )) {
100
+ /* Have two pointers current and prev */
101
+ Node <T > current = head ;
102
+ Node <T > prev = head ;
103
+ /* Keep going while current is not null */
104
+ while (current != null ) {
105
+ if (current .item == item ) {
106
+ /* If item matches, check if it is a head or not */
107
+ if (current == head ) {
108
+ /* If it's head, decrement the value and update head */
109
+ current .decrementValue ();
110
+ if (current .value < 1 ) {
111
+ head = head .next ;
112
+ }
113
+ return true ;
114
+ } else {
115
+ /* Decrement the value, check if this was the last
116
+ * entry of that type, it yes, delete the item */
117
+ current .decrementValue ();
118
+ if (current .value < 1 ) {
119
+ prev .next = current .next ;
120
+ current .next = null ;
121
+ }
122
+ return true ;
123
+ }
124
+ }
125
+ /* Move to next set of items */
126
+ prev = current ;
127
+ current = current .next ;
128
+ }
129
+ }
130
+ return false ;
131
+ }
132
+
133
+ /**
134
+ * Method to clear the bag
135
+ */
136
+ public void clear () {
137
+ this .head = null ;
138
+ }
139
+
140
+ /**
141
+ * Method to check if bag contains the item
142
+ *
143
+ * @param item
144
+ * @return {@link boolean}
145
+ */
146
+ public boolean contains (T item ) {
147
+ Node <T > current = head ;
148
+ /* Start traversing and stop if item matches */
149
+ while (current != null ) {
150
+ if (current .item == item ) {
151
+ return true ;
152
+ }
153
+ current = current .next ;
154
+ }
155
+ return false ;
156
+ }
157
+
158
+ /**
159
+ * Method to grab any random element
160
+ *
161
+ * @return {@link T}
162
+ */
163
+ public T grab () {
164
+ /* Have a random index */
165
+ Random random = new Random ();
166
+ int randomItemIndex = random .nextInt (distinctSize ());
167
+ Node <T > current = head ;
168
+ /* Move the pointer till we reach that random index */
169
+ for (int i = 0 ; i < randomItemIndex ; i ++) {
170
+ current = current .next ;
171
+ }
172
+ return current .item ;
173
+ }
174
+
175
+ /**
176
+ * Method to check size of the bag
177
+ *
178
+ * @return {@link int}
179
+ */
180
+ public int size () {
181
+ Node <T > current = head ;
182
+ int size = 0 ;
183
+ /* Keep traversing and track size of each entry */
184
+ while (current != null ) {
185
+ size += current .value ;
186
+ current = current .next ;
187
+ }
188
+ return size ;
189
+ }
190
+
191
+ /**
192
+ * Method to get distinct size of the bag
193
+ *
194
+ * @return {@link int}
195
+ */
196
+ public int distinctSize () {
197
+ Node <T > current = head ;
198
+ int counter = 0 ;
199
+ /* Increment the counter only when a new element is seen */
200
+ while (current != null ) {
201
+ counter ++;
202
+ current = current .next ;
203
+ }
204
+ return counter ;
205
+ }
206
+
207
+ /**
208
+ * Method to check if bag is empty
209
+ *
210
+ * @return {@link boolean}
211
+ */
212
+ public boolean isEmpty () {
213
+ if (head == null ) {
214
+ return true ;
215
+ }
216
+ return false ;
217
+ }
218
+
219
+ /**
220
+ * Method to print the content of bag as string
221
+ */
222
+ public String toString () {
223
+ if (isEmpty ()) {
224
+ return "Bag is Empty" ;
225
+ } else {
226
+ /* Keep appending the elements to string */
227
+ Node <T > current = head ;
228
+ String str = "Bag = " ;
229
+ while (current != null ) {
230
+ for (int i = 0 ; i < current .value ; i ++) {
231
+ str += "{" + current .item + "}" ;
232
+ }
233
+ current = current .next ;
234
+ }
235
+ return str ;
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Method to get a iterator on bag
241
+ *
242
+ * @return {@link Iterator<T>}
243
+ */
244
+ public Iterator <T > iterator () {
245
+ return new Iterator <T >() {
246
+
247
+ /* Keep a track of next item and value count for each item */
248
+ private Node <T > nextItem = head ;
249
+ private int valueCount = 0 ;
250
+
251
+ /**
252
+ * Method to check if bag has elements
253
+ */
254
+ @ Override
255
+ public boolean hasNext () {
256
+ /* If next item is head and it's not null,
257
+ * we have more elements */
258
+ if (nextItem == head && nextItem != null ) {
259
+ return true ;
260
+ } else if (nextItem != head && nextItem .next != null ){
261
+ return true ;
262
+ } else if (nextItem .value > valueCount + 1 ) {
263
+ return true ;
264
+ }
265
+ return false ;
266
+ }
267
+
268
+ /**
269
+ * Method to get the next element
270
+ */
271
+ @ Override
272
+ public T next () {
273
+ if (!hasNext ()) {
274
+ throw new NoSuchElementException ("No Element left in collection" );
275
+ }
276
+ if (nextItem .value > valueCount ) {
277
+ /* We still have items of same type left */
278
+ valueCount ++;
279
+ } else {
280
+ /* Time to move to next item */
281
+ nextItem = nextItem .next ;
282
+ valueCount = 0 ;
283
+ }
284
+ Node <T > itemToReturn = nextItem ;
285
+ if (itemToReturn != null ) {
286
+ return itemToReturn .item ;
287
+ } else {
288
+ return null ;
289
+ }
290
+ }
291
+
292
+ };
293
+ }
294
+
295
+ /**
296
+ * Class Node for Bag
297
+ *
298
+ * @author Deepak
299
+ *
300
+ * @param <E>
301
+ */
302
+ public class Node <E > {
303
+
304
+ /* Item, counter associated with item and next pointer */
305
+ private E item ;
306
+ private int value ;
307
+ private Node <E > next ;
308
+
309
+ /**
310
+ * Constructor to create the Node
311
+ *
312
+ * @param item
313
+ */
314
+ public Node (E item ) {
315
+ this .item = item ;
316
+ this .value = 1 ;
317
+ this .next = null ;
318
+ }
319
+
320
+ /**
321
+ * Method to increment the value
322
+ */
323
+ public void incrementValue () {
324
+ value ++;
325
+ }
326
+
327
+ /**
328
+ * Method to decrement the value
329
+ */
330
+ public void decrementValue () {
331
+ value --;
332
+ }
333
+
334
+ @ Override
335
+ public String toString () {
336
+ return "Item : [" + this .item + "]" ;
337
+ }
338
+
339
+ }
340
+
341
+ }
0 commit comments