-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLeftistHeap.cc
125 lines (109 loc) · 2.77 KB
/
LeftistHeap.cc
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
#include <cassert>
#include <concepts>
#include <functional>
#include <print>
#include <random>
#include <utility>
// leftist heap is a binary tree
// leftist heap is also a heap
template <class T, class Comparator>
requires std::totally_ordered<T>
struct LeftistHeap {
struct Node {
// parent->e >= left->e
// parent->e >= right->e
T e;
Node *left{nullptr}, *right{nullptr};
// npl(leaf) = 1
// npl(left) >= npl(right)
int npl{1};
Node(T e) : e{e} {}
};
Comparator comparator;
Node *root{nullptr};
bool empty() const { return root == nullptr; }
void insert(T x) { root = merge(root, new Node(x)); }
T delMax() {
T e = root->e;
Node *l{root->left}, *r{root->right};
delete root;
root = merge(l, r);
return e;
}
void merge(LeftistHeap &rhs) {
if (this == &rhs)
return;
root = merge(root, rhs.root);
rhs.root = nullptr;
}
Node *merge(Node *a, Node *b) {
if (a == nullptr)
return b;
if (b == nullptr)
return a;
if (comparator(a->e, b->e))
std::swap(a, b);
// left is null => right is null
if (a->left == nullptr)
a->left = b;
else {
a->right = merge(a->right, b);
// skew heap always swap l and r
if (a->left->npl < a->right->npl)
std::swap(a->left, a->right);
a->npl = a->right->npl + 1;
}
return a;
}
LeftistHeap(auto comparator) : comparator{comparator} {}
~LeftistHeap() { destroy(root); }
void destroy(Node *x) {
if (x == nullptr)
return;
destroy(x->left);
destroy(x->right);
delete x;
}
bool isLeftistHeap() { return isLeftistHeap(root); }
bool isLeftistHeap(Node *x) {
if (x == nullptr)
return true;
if (x->left && comparator(x->e, x->left->e))
return false;
if (x->right && comparator(x->e, x->right->e))
return false;
if (nullPathLength(x->left) < nullPathLength(x->right))
return false;
return isLeftistHeap(x->left) && isLeftistHeap(x->right);
}
int nullPathLength(Node *x) {
if (x == nullptr)
return 0;
return x->npl;
}
};
int main() {
std::mt19937 mt(std::random_device{}());
std::uniform_int_distribution rand(10, 99);
LeftistHeap<int, std::function<bool(int, int)>> maxpq(
[](auto &&v, auto &&w) { return v > w; }),
maxqp([](auto &&v, auto &&w) { return v > w; });
std::print("vector\t");
for (int i = 0; i < 8; i++) {
int e = rand(mt);
maxpq.insert(e);
assert(maxpq.isLeftistHeap());
maxqp.insert(e);
assert(maxqp.isLeftistHeap());
std::print("{}\t", e);
}
std::print("\n");
maxpq.merge(maxqp);
assert(maxpq.isLeftistHeap());
std::print("max\t");
while (!maxpq.empty()) {
std::print("{}\t", maxpq.delMax());
assert(maxpq.isLeftistHeap());
}
std::print("\n");
}