Container¶
Priority Queue¶
Priority Queue¶
#include <iostream>
#include <functional>
#include <vector>
#include <queue>
template<typename Q>
void dump(Q &q) {
while(!q.empty()) {
std::cout << q.top() << " ";
q.pop();
}
std::cout << "\n";
}
void foo() {
std::vector<int> data{1, 5, 2, 1, 3};
std::priority_queue<int> queue;
for (auto & x : data) { queue.push(x); }
dump(queue);
}
void bar() {
std::vector<int> data{1, 5, 2, 1, 3};
std::priority_queue<int, std::vector<int>, std::greater<int>> queue;
for (auto & x : data) { queue.push(x); }
dump(queue);
}
void baz() {
std::vector<int> data{1, 5, 2, 1, 3};
auto cmp = [](int x, int y) { return x < y; };
std::priority_queue<int, std::vector<int>, decltype(cmp)> queue(cmp);
for (auto & x : data) { queue.push(x); }
dump(queue);
}
int main(int argc, char *argv[]) {
foo();
bar();
baz();
// 5 3 2 1 1
// 1 1 2 3 5
// 1 1 2 3 5
}
Priority queue is useful when a programmer need to merge multiple lists of data in order.
#include <iostream>
#include <vector>
#include <queue>
template<typename Q>
void dump(Q &q) {
while(!q.empty()) {
std::cout << q.top() << " ";
q.pop();
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
std::priority_queue<int> queue;
std::vector<int> x{9, 7, 8};
std::vector<int> y{0, 5, 3};
for (auto &e : x) { queue.push(e); }
for (auto &e : y) { queue.push(e); }
dump(queue);
// 9 8 7 5 3 0
}
Profiling¶
// profile.h
#include <iostream>
#include <chrono>
using milliseconds = std::chrono::milliseconds;
template <typename T, typename F>
void profile(T &t, F &func) {
const auto start = std::chrono::steady_clock::now();
func(t);
const auto end = std::chrono::steady_clock::now();
const auto d = end - start;
const auto mill = std::chrono::duration_cast<milliseconds>(d).count();
std::cout << mill << " ms\n";
}
Push Front¶
// g++ -O3 -std=c++17 -Wall -Werror -I${HDR} a.cpp
#include <vector>
#include <deque>
#include <list>
#include <range/v3/view/iota.hpp>
#include "profile.h"
template <typename T>
void insert(T &t) {
for (auto i : ranges::views::iota(0, 300000)) {
t.insert(t.begin(), i);
}
}
int main(int argc, char *argv[]) {
std::vector<int> v;
std::deque<int> q;
std::list<int> l;
profile(v, insert<decltype(v)>);
profile(q, insert<decltype(q)>);
profile(l, insert<decltype(l)>);
}
$ ./a.out
16045 ms
1 ms
6 ms
Push Back¶
#include <vector>
#include <deque>
#include <list>
#include <range/v3/view/iota.hpp>
#include "profile.h"
template <typename T>
void insert(T &t) {
for (auto i : ranges::views::iota(0, 1000000)) {
t.push_back(i);
}
}
int main(int argc, char *argv[]) {
std::vector<int> v;
std::deque<int> q;
std::list<int> l;
profile(v, insert<decltype(v)>);
profile(q, insert<decltype(q)>);
profile(l, insert<decltype(l)>);
}
./a.out
7 ms
2 ms
39 ms
Pop Front¶
#include <vector>
#include <deque>
#include <list>
#include <range/v3/view/iota.hpp>
#include "profile.h"
template <typename T>
void insert(T &t) {
for (auto i : ranges::views::iota(0, 300000)) {
t.push_back(i);
}
}
template <typename T>
void pop_front(T &t) {
while (!t.empty()) {
t.pop_front();
}
}
template <typename T>
void erase(T &v) {
while(!v.empty()) {
v.erase(v.begin());
}
}
int main(int argc, char *argv[]) {
std::vector<int> v;
std::deque<int> q;
std::list<int> l;
insert(v); insert(q); insert(l);
profile(v, erase<decltype(v)>);
profile(q, pop_front<decltype(q)>);
profile(l, pop_front<decltype(l)>);
}
$ ./a.out
22923 ms
0 ms
12 ms
Pop Back¶
#include <vector>
#include <deque>
#include <list>
#include <range/v3/view/iota.hpp>
#include "profile.h"
template <typename T>
void insert(T &t) {
for (auto i : ranges::views::iota(0, 1000000)) {
t.push_back(i);
}
}
template <typename T>
void pop_back(T &t) {
while (!t.empty()) {
t.pop_back();
}
}
int main(int argc, char *argv[]) {
std::vector<int> v;
std::deque<int> q;
std::list<int> l;
insert(v); insert(q); insert(l);
profile(v, pop_back<decltype(v)>);
profile(q, pop_back<decltype(q)>);
profile(l, pop_back<decltype(l)>);
}
$ ./a.out
0 ms
0 ms
30 ms