leftist_heap.hpp¶
提供可快速合并的优先队列;题目频繁合并两堆元素并取出极值时使用。
Complexity: Time: O(log n) push/pop/meld. Space: O(n) nodes and O(log n) stack.
Implementation¶
当前头文件,省略 include guard;依赖见 #include。
/// @complexity Time: O(log n) push/pop/meld.
/// Space: O(n) nodes and O(log n) stack.
#include <cassert>
#include <functional>
#include <utility>
namespace noya {
/// @brief Meldable leftist heap with O(log n) push, pop, and heap merging.
template <class T, class Compare = std::less<T>> struct leftist_heap {
struct node {
T val;
node *ls = nullptr;
node *rs = nullptr;
int rk = 1;
};
node *rt = nullptr;
Compare cmp{};
leftist_heap() = default;
leftist_heap(const leftist_heap &) = delete;
leftist_heap &operator=(const leftist_heap &) = delete;
leftist_heap(leftist_heap &&rhs) noexcept
: rt(std::exchange(rhs.rt, nullptr)), cmp(std::move(rhs.cmp)) {}
leftist_heap &operator=(leftist_heap &&rhs) noexcept {
if (this != &rhs) {
clear(rt);
rt = std::exchange(rhs.rt, nullptr);
cmp = std::move(rhs.cmp);
}
return *this;
}
~leftist_heap() { clear(rt); }
bool empty() const { return rt == nullptr; }
const T &top() const {
assert(rt != nullptr);
return rt->val;
}
void push(const T &val) { rt = meld(rt, new node{val}); }
void push(T &&val) { rt = meld(rt, new node{std::move(val)}); }
void pop() {
assert(rt != nullptr);
node *old = rt;
rt = meld(rt->ls, rt->rs);
delete old;
}
void merge(leftist_heap &rhs) {
if (this != &rhs) {
rt = meld(rt, std::exchange(rhs.rt, nullptr));
}
}
private:
int rank(node *cur) const { return cur == nullptr ? 0 : cur->rk; }
node *meld(node *a, node *b) {
if (a == nullptr || b == nullptr) {
return a == nullptr ? b : a;
}
if (cmp(b->val, a->val)) {
std::swap(a, b);
}
a->rs = meld(a->rs, b);
if (rank(a->ls) < rank(a->rs)) {
std::swap(a->ls, a->rs);
}
a->rk = rank(a->rs) + 1;
return a;
}
void clear(node *cur) {
if (cur != nullptr) {
clear(cur->ls);
clear(cur->rs);
delete cur;
}
}
};
} // namespace noya
#ifndef NOYA_LEFTIST_HEAP_HPP
#define NOYA_LEFTIST_HEAP_HPP 1
/// @complexity Time: O(log n) push/pop/meld.
/// Space: O(n) nodes and O(log n) stack.
#include <cassert>
#include <functional>
#include <utility>
namespace noya {
/// @brief Meldable leftist heap with O(log n) push, pop, and heap merging.
template <class T, class Compare = std::less<T>> struct leftist_heap {
struct node {
T val;
node *ls = nullptr;
node *rs = nullptr;
int rk = 1;
};
node *rt = nullptr;
Compare cmp{};
leftist_heap() = default;
leftist_heap(const leftist_heap &) = delete;
leftist_heap &operator=(const leftist_heap &) = delete;
leftist_heap(leftist_heap &&rhs) noexcept
: rt(std::exchange(rhs.rt, nullptr)), cmp(std::move(rhs.cmp)) {}
leftist_heap &operator=(leftist_heap &&rhs) noexcept {
if (this != &rhs) {
clear(rt);
rt = std::exchange(rhs.rt, nullptr);
cmp = std::move(rhs.cmp);
}
return *this;
}
~leftist_heap() { clear(rt); }
bool empty() const { return rt == nullptr; }
const T &top() const {
assert(rt != nullptr);
return rt->val;
}
void push(const T &val) { rt = meld(rt, new node{val}); }
void push(T &&val) { rt = meld(rt, new node{std::move(val)}); }
void pop() {
assert(rt != nullptr);
node *old = rt;
rt = meld(rt->ls, rt->rs);
delete old;
}
void merge(leftist_heap &rhs) {
if (this != &rhs) {
rt = meld(rt, std::exchange(rhs.rt, nullptr));
}
}
private:
int rank(node *cur) const { return cur == nullptr ? 0 : cur->rk; }
node *meld(node *a, node *b) {
if (a == nullptr || b == nullptr) {
return a == nullptr ? b : a;
}
if (cmp(b->val, a->val)) {
std::swap(a, b);
}
a->rs = meld(a->rs, b);
if (rank(a->ls) < rank(a->rs)) {
std::swap(a->ls, a->rs);
}
a->rk = rank(a->rs) + 1;
return a;
}
void clear(node *cur) {
if (cur != nullptr) {
clear(cur->ls);
clear(cur->rs);
delete cur;
}
}
};
} // namespace noya
#endif // NOYA_LEFTIST_HEAP_HPP
#include <cassert>
#include <functional>
#include <utility>
/// @complexity Time: O(log n) push/pop/meld.
/// Space: O(n) nodes and O(log n) stack.
namespace noya {
/// @brief Meldable leftist heap with O(log n) push, pop, and heap merging.
template <class T, class Compare = std::less<T>> struct leftist_heap {
struct node {
T val;
node *ls = nullptr;
node *rs = nullptr;
int rk = 1;
};
node *rt = nullptr;
Compare cmp{};
leftist_heap() = default;
leftist_heap(const leftist_heap &) = delete;
leftist_heap &operator=(const leftist_heap &) = delete;
leftist_heap(leftist_heap &&rhs) noexcept
: rt(std::exchange(rhs.rt, nullptr)), cmp(std::move(rhs.cmp)) {}
leftist_heap &operator=(leftist_heap &&rhs) noexcept {
if (this != &rhs) {
clear(rt);
rt = std::exchange(rhs.rt, nullptr);
cmp = std::move(rhs.cmp);
}
return *this;
}
~leftist_heap() { clear(rt); }
bool empty() const { return rt == nullptr; }
const T &top() const {
assert(rt != nullptr);
return rt->val;
}
void push(const T &val) { rt = meld(rt, new node{val}); }
void push(T &&val) { rt = meld(rt, new node{std::move(val)}); }
void pop() {
assert(rt != nullptr);
node *old = rt;
rt = meld(rt->ls, rt->rs);
delete old;
}
void merge(leftist_heap &rhs) {
if (this != &rhs) {
rt = meld(rt, std::exchange(rhs.rt, nullptr));
}
}
private:
int rank(node *cur) const { return cur == nullptr ? 0 : cur->rk; }
node *meld(node *a, node *b) {
if (a == nullptr || b == nullptr) {
return a == nullptr ? b : a;
}
if (cmp(b->val, a->val)) {
std::swap(a, b);
}
a->rs = meld(a->rs, b);
if (rank(a->ls) < rank(a->rs)) {
std::swap(a->ls, a->rs);
}
a->rk = rank(a->rs) + 1;
return a;
}
void clear(node *cur) {
if (cur != nullptr) {
clear(cur->ls);
clear(cur->rs);
delete cur;
}
}
};
} // namespace noya