1
+ #ifndef VPR_LAZY_POP_UNIQUE_PRIORITY_QUEUE_H
2
+ #define VPR_LAZY_POP_UNIQUE_PRIORITY_QUEUE_H
3
+
4
+ #include < unordered_set>
5
+ #include < vector>
6
+ #include < algorithm>
7
+
8
+ /* *
9
+ * @brief Lazy Pop Unique Priority Queue
10
+ *
11
+ * This is a priority queue that is used to sort items which are identified by the key
12
+ * and sorted by the sort value.
13
+ *
14
+ * It uses a vector to store the key and sort value pair.
15
+ * It uses a set to store the keys that are in the vector for uniqueness checking
16
+ * and a set to store the delete pending keys which will be removed at pop time.
17
+ */
18
+ template <typename T_key, typename T_sort>
19
+ class LazyPopUniquePriorityQueue {
20
+ public:
21
+ /* * @brief The custom comparsion struct for sorting the items in the priority queue.
22
+ * A less than comparison will put the item with the highest sort value to the front of the queue.
23
+ * A greater than comparison will put the item with the lowest sort value to the front of the queue.
24
+ */
25
+ struct LazyPopUniquePriorityQueueCompare {
26
+ bool operator ()(const std::pair<T_key, T_sort>& a,
27
+ const std::pair<T_key, T_sort>& b) const {
28
+ return a.second < b.second ;
29
+ }
30
+ };
31
+
32
+ // / @brief The vector maintained as heap to store the key and sort value pair.
33
+ std::vector<std::pair<T_key, T_sort>> heap;
34
+
35
+ // / @brief The set to store the keys that are in the queue. This is used to ensure uniqueness
36
+ std::unordered_set<T_key> content_set;
37
+
38
+ // / @brief The set to store the delete pending item from the queue refered by the key.
39
+ std::unordered_set<T_key> delete_pending_set;
40
+
41
+ /* *
42
+ * @brief Push the key and the sort value as a pair into the priority queue.
43
+ *
44
+ * @param key
45
+ * The unique key for the item that will be pushed onto the queue.
46
+ * @param value
47
+ * The sort value used for sorting the item.
48
+ */
49
+ void push (T_key key, T_sort value){
50
+ // Insert the key and sort value pair into the queue if it is not already present
51
+ if (content_set.find (key) != content_set.end ()) {
52
+ // If the key is already in the queue, do nothing
53
+ return ;
54
+ }
55
+ heap.emplace_back (key, value);
56
+ std::push_heap (heap.begin (),
57
+ heap.end (),
58
+ LazyPopUniquePriorityQueueCompare ());
59
+ content_set.insert (key);
60
+ }
61
+
62
+ /* *
63
+ * @brief Pop the top item from the priority queue.
64
+ *
65
+ * @return The key and sort value pair.
66
+ */
67
+ std::pair<T_key,T_sort> pop (){
68
+ std::pair<T_key, T_sort> top_pair;
69
+ while (heap.size () > 0 ) {
70
+ top_pair = heap.front ();
71
+ // remove the key from the heap and the tracking set
72
+ std::pop_heap (heap.begin (),
73
+ heap.end (),
74
+ LazyPopUniquePriorityQueueCompare ());
75
+ heap.pop_back ();
76
+ content_set.erase (top_pair.first );
77
+
78
+ // checking if the highest value's key is in the delete pending set
79
+ // if it is, remove it from the delete pending set and find the next best gain's key
80
+ if (delete_pending_set.find (top_pair.first ) != delete_pending_set.end ()) {
81
+ delete_pending_set.erase (top_pair.first );
82
+ top_pair = std::pair<T_key, T_sort>();
83
+ } else {
84
+ break ;
85
+ }
86
+ }
87
+ return top_pair;
88
+ }
89
+
90
+ /* *
91
+ * @brief Remove the item with matching key value from the priority queue
92
+ * This fill immediately remove the item and re-heapify the queue.
93
+ *
94
+ * @param key
95
+ * The key of the item to be delected from the queue
96
+ */
97
+ void remove (T_key key){
98
+ // If the key is in the priority queue, remove it from the heap and reheapify
99
+ // Otherwise, do nothing.
100
+ if (content_set.find (key) != content_set.end ()) {
101
+ content_set.erase (key);
102
+ delete_pending_set.erase (key);
103
+ for (int i = 0 ; i < heap.size (); i++) {
104
+ if (heap[i].first == key) {
105
+ heap.erase (heap.begin () + i);
106
+ break ;
107
+ }
108
+ }
109
+ std::make_heap (heap.begin (), heap.end (), LazyPopUniquePriorityQueueCompare ());
110
+ }
111
+ }
112
+
113
+
114
+ /* *
115
+ * @brief Remove the item with matching key value from the priority queue at pop time.
116
+ * Add the key to the delete pending set for tracking,
117
+ * and it will be deleted when it is popped.
118
+ *
119
+ * This function will not immediately delete the key from the
120
+ * priority queue. It will be deleted when it is popped. Thus do not
121
+ * expect a size reduction in the priority queue immediately.
122
+ * @param key
123
+ * The key of the item to be delected from the queue at pop time.
124
+ */
125
+ void remove_at_pop_time (T_key key){
126
+ // if the key is in the list, start tracking it in the delete pending list.
127
+ // Otherwise, do nothing.
128
+ if (content_set.find (key) != content_set.end ()) {
129
+ delete_pending_set.insert (key);
130
+ }
131
+ }
132
+
133
+ /* *
134
+ * @brief Check if the priority queue is empty.
135
+ *
136
+ * @return True if the priority queue is empty, false otherwise.
137
+ */
138
+ bool empty (){
139
+ return heap.empty ();
140
+ }
141
+
142
+ /* *
143
+ * @brief Clears the priority queue and the tracking sets.
144
+ *
145
+ * @return None
146
+ */
147
+ void clear (){
148
+ heap.clear ();
149
+ content_set.clear ();
150
+ delete_pending_set.clear ();
151
+ }
152
+
153
+ /* *
154
+ * @brief Get the size of the priority queue.
155
+ *
156
+ * @return The size of the priority queue.
157
+ */
158
+ size_t size (){
159
+ return heap.size ();
160
+ }
161
+
162
+ /* *
163
+ * @brief Check if the item refered by the key is in the priority queue.
164
+ *
165
+ * @param key
166
+ * The key of the item.
167
+ * @return True if the key is in the priority queue, false otherwise.
168
+ */
169
+ bool contains (T_key key){
170
+ return content_set.find (key) != content_set.end ();
171
+ }
172
+ };
173
+
174
+ #endif
0 commit comments