-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheap.cpp
More file actions
134 lines (110 loc) · 2.72 KB
/
heap.cpp
File metadata and controls
134 lines (110 loc) · 2.72 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
/**
* @file heap.cpp
* @brief
* @author Haoming Bai <haomingbai@hotmail.com>
* @date 2025-08-22
*
* Copyright © 2025 Haoming Bai
* SPDX-License-Identifier: MIT
*
* @details
*/
#include <cassert>
#include <cstddef>
#include <functional>
#include <utility>
#include <vector>
template <typename T, typename C = std::less<T>>
class Heap {
public:
template <typename... Args>
bool Push(Args&&... val) {
auto curr_idx = container_.size();
container_.emplace_back(std::forward<Args>(val)...);
T tmp = std::move(container_.back());
// Modify the heap.
{
auto child = curr_idx;
auto parent = child / 2;
while (parent) {
if (comp_(container_[parent], tmp)) {
container_[child] = std::move(container_[parent]);
child = parent;
parent /= 2;
} else {
break;
}
}
container_[child] = std::move(tmp);
}
return true;
}
T Pop() noexcept {
constexpr std::size_t root = 1;
auto last_idx = container_.size() - 1;
auto result = std::move(container_[root]);
auto tmp = std::move(container_[last_idx]);
container_.pop_back();
{
last_idx--;
if (last_idx < 1) {
return result;
}
auto curr = root;
while (curr * 2 <= last_idx) {
auto left = curr * 2;
auto right = left + 1;
[[unlikely]] if (right > last_idx) {
if (comp_(tmp, container_[left])) {
container_[curr] = std::move(container_[left]);
curr = left;
} else {
break;
}
} else {
assert(right <= last_idx);
auto to_comp =
comp_(container_[left], container_[right]) ? right : left;
if (comp_(tmp, container_[to_comp])) {
container_[curr] = std::move(container_[to_comp]);
curr = to_comp;
} else {
break;
}
}
}
container_[curr] = std::move(tmp);
}
return result;
}
const T& Top() const noexcept {
assert(!IsEmpty());
return container_[1];
}
bool ShrinkToFit() {
container_.shrink_to_fit();
return true;
}
std::size_t GetSize() const noexcept {
assert(container_.size());
return container_.size() - 1;
}
std::size_t GetCapacity() const noexcept {
assert(container_.capacity());
return container_.capacity() - 1;
}
bool IsEmpty() const noexcept {
assert(container_.size());
return (container_.size() <= 1);
}
bool Reserve(std::size_t n) {
container_.reserve(n + 1);
return true;
}
Heap() : container_(1) {}
template <typename... Comp>
Heap() : container_(1) {}
private:
std::vector<T> container_;
static C comp_;
};