-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMinPQ.hpp
More file actions
213 lines (187 loc) · 6.02 KB
/
MinPQ.hpp
File metadata and controls
213 lines (187 loc) · 6.02 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
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
#ifndef ALGORITHMS_MINPQ_HPP
#define ALGORITHMS_MINPQ_HPP
#include <span> // std::span
#include <array> // std::array
#include <vector> // std::vector
#include "Comparable.hpp" // includes Comparable concept used as a constraint
#include <cassert> // std::assert
#include <boost/lexical_cast.hpp> // boost::lexical_cast
using namespace std;
/**
* The {@code MinPQ} class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-minimum
* operations, along with methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a binary heap.
* The insert and delete-the-minimum operations take
* Θ(log(n)) amortized time, where n is the number
* of elements in the priority queue. This is an amortized bound
* (and not a worst-case bound) because of array resizing operations.
* The min, size, and is-empty operations take
* Θ(1) time in the worst case.
* Construction takes time proportional to the specified capacity or the
* number of items used to initialize the data structure.
*
* @author Benjamin Chan
*
* Adapted from Algorithms, 4th edition, {@authors Robert Sedgewick and Kevin Wayne}
* and their booksite https://algs4.cs.princeton.edu/
*
* The Java program from which this C++ code was adapted from is found at
* https://algs4.cs.princeton.edu/24pq/MinPQ.java.html.
*
* @param <T> the generic type of key on this priority queue
*/
template<typename T> requires Comparable<T>
class MinPQ {
public:
/**
* Initializes an empty priority queue.
*/
MinPQ() {
this->n = 0;
}
/**
* Initializes a priority queue from the array of keys.
* Takes time proportional to the number of keys, using sink-based heap construction.
*
* @param keys the array of keys
*/
explicit MinPQ(vector<T> keys) {
n = keys.size();
pq = vector<T>(n + 1);
for (int i = 0; i < n; i++)
pq[i + 1] = keys[i];
for (int k = n / 2; k >= 1; k--)
sink(k);
}
/**
* Returns true if this priority queue is empty.
*
* @return {@code true} if this priority queue is empty;
* {@code false} otherwise
*/
bool isEmpty() {
return n == 0;
}
/**
* Returns the number of keys on this priority queue.
*
* @return the number of keys on this priority queue
*/
int size() {
return n;
}
/**
* Returns a largest key on this priority queue.
*
* @return a largest key on this priority queue
* @throws NoSuchElementException if this priority queue is empty
*/
T max() {
try {
if (isEmpty()) throw NoSuchElementException();
return pq[1];
}
catch (NoSuchElementException &e) {
std::cout << "NoSuchElementException encountered: ";
std::cout << e.what() << std::endl;
}
}
/**
* Adds a new key to this priority queue.
*
* @param x the new key to add to this priority queue
*/
void insert(T x) {
// add x, and percolate it up to maintain heap invariant
pq.push_back(x);
swim(n);
}
/**
* Removes and returns a largest key on this priority queue.
*
* @return a largest key on this priority queue
* @throws NoSuchElementException if this priority queue is empty
*/
T delMin() {
try {
if (isEmpty()) throw NoSuchElementException();
T max = pq[1];
exch(1, n--);
sink(1);
pq.erase(pq.begin() + n + 1);
return max;
}
catch (NoSuchElementException &e) {
std::cout << "NoSuchElementException encountered: ";
std::cout << e.what() << std::endl;
}
}
/**
* Returns a string representation of this minimum priority queue.
*
* @return the sequence of items in ascending order, separated by spaces
*/
[[nodiscard]] std::string toString() const;
private:
vector<T> pq; // store items at indices 1 to n
int n{}; // number of items on priority queue
/**
* @def the NoSuchElementException if there are no items in the priority queue after
* using the max(), methods
*/
struct NoSuchElementException : public std::exception {
const char *what() {
return "Priority Queue Underflow";
}
};
/***************************************************************************
* Helper functions to restore the heap invariant.
***************************************************************************/
void swim(int k) {
while (k > 1 && pq[k / 2] > k) {
exch(k, k / 2);
k = k / 2;
}
}
void sink(int k) {
while (2 * k <= n) {
int j = 2 * k;
if (j < n && pq[j] > pq[j + 1]) j++;
if (pq[k] <= pq[j]) break;
exch(k, j);
k = j;
}
}
/***************************************************************************
* Helper functions for compares and swaps.
***************************************************************************/
void exch(int i, int j) {
T swap = pq[i];
pq[i] = pq[j];
pq[j] = swap;
}
};
template<typename T>
requires Comparable<T>
std::string MinPQ<T>::toString() const {
std::stringstream ss;
MinPQ<T> copy{this->pq};
while (!copy.isEmpty()) {
ss << boost::lexical_cast<std::string>(copy.delMin()) << " ";
}
ss << endl;
return ss.str();
}
/// Overloads the "<<" operator for a bag
template<typename T>
std::ostream &operator<<(std::ostream &os, const MinPQ<T> &minPQ) {
return os << minPQ.toString();
}
/// Uses type deduction for one of the constructors
template<typename T> requires Comparable<T>
MinPQ(vector<T>)->MinPQ<T>;
#endif //ALGORITHMS_MINPQ_HPP