-
Notifications
You must be signed in to change notification settings - Fork 0
/
TopKHeap.java
127 lines (112 loc) · 4.37 KB
/
TopKHeap.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
import java.util.Map;
import java.util.HashMap;
import java.util.List;
public class TopKHeap<T extends Comparable<T>> {
private BinaryMinHeap<T> topK; // Holds the top k items
private BinaryMaxHeap<T> rest; // Holds all items other than the top k
private int size; // Maintains the size of the data structure
private final int k; // The value of k
private Map<T, MyPriorityQueue<T>> itemToHeap; // Keeps track of which heap contains each item.
// Creates a topKHeap for the given choice of k.
public TopKHeap(int k){
topK = new BinaryMinHeap<>();
rest = new BinaryMaxHeap<>();
size = 0;
this.k = k;
itemToHeap = new HashMap<>();
}
// Returns a list containing exactly the
// largest k items. The list is not necessarily
// sorted. If the size is less than or equal to
// k then the list will contain all items.
// The running time of this method should be O(k).
public List<T> topK(){
return topK.toList();
}
// Add the given item into the data structure.
// The running time of this method should be O(log(n)+log(k)).
public void insert(T item){
if (topK.size() < k) {
topK.insert(item);
itemToHeap.put(item, topK);
} else if (item.compareTo(topK.peek()) > 0) {
T removedTopK = topK.extract();
itemToHeap.remove(removedTopK);
rest.insert(removedTopK);
itemToHeap.put(removedTopK, rest);
topK.insert(item);
itemToHeap.put(item, topK);
} else {
rest.insert(item);
itemToHeap.put(item, rest);
}
size++;
}
// Indicates whether the given item is among the
// top k items. Should return false if the item
// is not present in the data structure at all.
// The running time of this method should be O(1).
// We have provided a suggested implementation,
// but you're welcome to do something different!
public boolean isTopK(T item){
return itemToHeap.get(item) == topK;
}
// To be used whenever an item's priority has changed.
// The input is a reference to the items whose priority
// has changed. This operation will then rearrange
// the items in the data structure to ensure it
// operates correctly.
// Throws an IllegalArgumentException if the item is
// not a member of the heap.
// The running time of this method should be O(log(n)+log(k)).
public void updatePriority(T item) {
if (!itemToHeap.containsKey(item)) {
throw new IllegalArgumentException("Item not found in the heap");
}
MyPriorityQueue<T> heap = itemToHeap.get(item);
heap.updatePriority(item);
if (heap == topK) {
if (topK.peek().compareTo(item) < 0) {
topK.remove(item);
itemToHeap.remove(item);
rest.insert(item);
itemToHeap.put(item, rest);
T restMax = rest.extract();
topK.insert(restMax);
itemToHeap.put(restMax, topK);
}
} else if (heap == rest) {
if (item.compareTo(topK.peek()) > 0) {
rest.remove(item);
itemToHeap.remove(item);
T removedTopK = topK.extract();
itemToHeap.remove(removedTopK);
rest.insert(removedTopK);
itemToHeap.put(removedTopK, rest);
topK.insert(item);
itemToHeap.put(item, topK);
}
}
}
// Removes the given item from the data structure
// throws an IllegalArgumentException if the item
// is not present.
// The running time of this method should be O(log(n)+log(k)).
public void remove(T item){
MyPriorityQueue<T> heap = itemToHeap.get(item);
if (heap == null) {
throw new IllegalArgumentException("Item not in heap");
}
heap.remove(item);
itemToHeap.remove(item);
if (heap == topK && rest.size() > 0) {
T movedItem = rest.extract();
topK.insert(movedItem);
itemToHeap.put(movedItem, topK);
}
size--;
}
public int size() {
return size;
}
}