-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathRandomizedQueue.java
More file actions
141 lines (125 loc) · 3.53 KB
/
Copy pathRandomizedQueue.java
File metadata and controls
141 lines (125 loc) · 3.53 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
import java.lang.Iterable;
import java.util.Iterator;
import java.util.Random;
import java.util.NoSuchElementException;
public class RandomizedQueue<Item> implements Iterable<Item>
{
private Item[] q;
private int first, last;
private Random rand; // for generating random numbers
public RandomizedQueue()
{
this.q = (Item[]) new Object[1];
this.first = 0;
this.last = 0; // always points to the next position after last element
this.rand = new Random();
}
public boolean isEmpty()
{
return first == 0;
}
public int size()
{
return (last - first);
}
/* Insert into the queue */
public void enqueue(Item item)
{
if (item == null) throw new NullPointerException("Cannot add null values.");
if (size() == q.length) resize(2*q.length);
if (last == q.length) resize(q.length); // resizing to same size repositions the array
// enqueue an element to the last
q[last++] = item;
}
/* helpers to enqueue */
private void resize(int capacity)
{
// Resizes and repositions the array to start from index 0
Item[] copy = (Item[]) new Object[capacity];
int size = size();
for (int i = 0; i < size; i++)
if (q[first+i] != null) // as items are deleted by keeping null in deleted positions
copy[i] = q[first + i];
q = copy;
}
/* Return and delete a randomly selected value from the queue */
public Item dequeue()
{
if (size() == 0) throw new NoSuchElementException("Cannot dequeue from an empty queue.");
// select a random value in [0, size]
int r = rand.nextInt(size());
int randomIndex = first + r;
// swap with last position
exch(randomIndex, last-1);
// now normal dequeue
Item item = q[--last];
q[last] = null;
if (size() == q.length/4) resize(q.length/2);
return item;
}
/* helpers to dequeue */
private void exch(int i, int j)
{
Item swap = q[i];
q[i] = q[j];
q[j] = swap;
}
/* Select and return a random value but do not delete it. */
public Item sample()
{
if (size() == 0) throw new NoSuchElementException("Cannot sample from an empty queue.");
// select a random value in [0, size]
int r = rand.nextInt(size());
int randomIndex = first + r;
return q[randomIndex];
}
/* Implementation of iteration functionality */
public Iterator<Item> iterator() { return new RandomizedQueueIterator(); }
private class RandomizedQueueIterator implements Iterator<Item>
{
private Item[] qCopy;
private int current;
public RandomizedQueueIterator()
{
this.qCopy = (Item[]) new Object[size()];
// copy the q
for (int i = 0; i < size() ; i++)
this.qCopy[i] = q[first + i];
// shuffle the queue's copy
Knuth.shuffle(this.qCopy);
this.current = 0;
}
public boolean hasNext()
{
return current != qCopy.length;
}
public void remove()
{
// not supported
throw new UnsupportedOperationException("remove() is not supported for iterators.");
}
public Item next()
{
if (!hasNext()) throw new NoSuchElementException("No more elements to iterate on.");
return qCopy[current++];
}
}
/* Unit testing */
public static void main(String[] args)
{
RandomizedQueue<String> rq = new RandomizedQueue<String>();
rq.enqueue("First");
rq.enqueue("Second");
rq.enqueue("Third");
rq.enqueue("Fourth");
rq.enqueue("Fifth");
for (String s : rq)
System.out.print(s + "\t");
System.out.println();
System.out.println("Sampled: " + rq.sample());
System.out.println("Sampled: " + rq.sample());
System.out.println("Sampled: " + rq.sample());
System.out.println("Removed: " + rq.dequeue());
System.out.println("Removed: " + rq.dequeue());
}
}