Skip to content

Commit c07cf8f

Browse files
committed
Add binary heap.
1 parent a794234 commit c07cf8f

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

heap.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* @file heap.cpp
3+
* @brief
4+
* @author Haoming Bai <haomingbai@hotmail.com>
5+
* @date 2025-08-22
6+
*
7+
* Copyright © 2025 Haoming Bai
8+
* SPDX-License-Identifier: MIT
9+
*
10+
* @details
11+
*/
12+
13+
#include <cassert>
14+
#include <cstddef>
15+
#include <functional>
16+
#include <utility>
17+
#include <vector>
18+
19+
template <typename DT, typename Compare = std::less<DT>>
20+
struct Heap {
21+
std::vector<DT> data_;
22+
Compare comp;
23+
24+
Heap() : data_(1), comp() {}
25+
26+
void push(const DT &elem) {
27+
data_.push_back(elem);
28+
29+
for (auto curr_idx = data_.size() - 1; curr_idx > 1;) {
30+
auto parent_idx = curr_idx / 2;
31+
32+
if (comp(data_[parent_idx], data_[curr_idx])) {
33+
std::swap(data_[parent_idx], data_[curr_idx]);
34+
curr_idx = parent_idx;
35+
} else {
36+
break;
37+
}
38+
}
39+
}
40+
41+
void pop() {
42+
std::swap(data_[1], data_.back());
43+
data_.pop_back();
44+
45+
for (size_t curr_idx = 1; curr_idx < data_.size();) {
46+
auto left_idx = curr_idx * 2;
47+
auto right_idx = curr_idx * 2 + 1;
48+
size_t child_idx = 0;
49+
50+
if (left_idx < data_.size()) {
51+
child_idx = left_idx;
52+
}
53+
if (right_idx < data_.size() && comp(data_[left_idx], data_[right_idx])) {
54+
child_idx = right_idx;
55+
}
56+
57+
if (child_idx && comp(data_[curr_idx], data_[child_idx])) {
58+
std::swap(data_[curr_idx], data_[child_idx]);
59+
curr_idx = child_idx;
60+
} else {
61+
break;
62+
}
63+
}
64+
}
65+
66+
const DT &top() { return data_[1]; }
67+
68+
bool empty() { return data_.size() <= 1; }
69+
70+
size_t size() { return data_.size() - 1; }
71+
};

main.tex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
co\_yield, char8\_t, char16\_t, char32\_t
7979
}
8080
}
81+
8182
\begin{document}
8283
\begin{titlepage}
8384
\centering
@@ -215,6 +216,12 @@ \section{单调栈}
215216

216217
\lstinputlisting[language=C++, caption=mono\_stack.cpp, style=MyCStyle]{./mono_stack.cpp}
217218

219+
\section{二叉堆}
220+
221+
二叉堆是一种基于完全二叉树的数据结构, 它满足堆序性质: 每个节点的值都大于等于或小于等于其子节点的值. 前者称为最大堆 (根节点最大), 后者称为最小堆 (根节点最小). 由于其完全二叉树的特性, 二叉堆通常使用数组实现, 可以高效地支持插入, 删除最大值/最小值等操作, 常用于实现优先队列或堆排序算法. 常见操作的时间复杂度为 $O(log n)$.
222+
223+
\lstinputlisting[language=C++, caption=heap.cpp, style=MyCStyle]{./heap.cpp}
224+
218225
\chapter{散列方法}
219226

220227
如果数据的范围过大, 就需要一些快速方法缩小这个范围. 例如对于1000个自然数-字符串对, 完全可以使用数组存储, 使用下标代表key, 但是如果简单地使用数组, 一旦数据中出现一个1000000000000-"xyz", 那么内存占用就会过大. 这时候, 合适的散列方法就相当重要.

0 commit comments

Comments
 (0)