Skip to content

Commit 51ea44a

Browse files
Update/content with code editing (#62)
* feat(online-compiler): 源码默认可见 + 左右分栏布局 - 桌面左右分栏(源码 | 操作+结果),<912px 自动上下 - 源码进入视口懒加载(IntersectionObserver),减少并发请求 - 编辑源码改为 toggle:再点保存编辑内容并切回只读预览 - 有 ARM 源码时加「源码/ARM 精简源码」tab,看 ARM 汇编自动对照 - 本期纯文本等宽,shiki 语法高亮留作后续 * feat: vol3 writes, refactorizing and todo sync * feat(online-compiler): 源码区 C++ 语法高亮(shiki) - 只读源码用 shiki/bundle/web runtime 高亮,复用 github-light/dark 双主题 - 动态 import + 单例懒加载,不污染首屏 bundle(shiki 已随 vitepress 安装,无需加依赖) - 双主题经 html.dark + --shiki-light/dark 变量自动切换,无需刷新 - 高亮异步:未就绪先纯文本 fallback,就绪后替换为着色 HTML - 编辑态 textarea 保持纯文本(编辑场景不高亮) * feat: refactor the old passages * feat: c++26 formater support and new passages * feat(vol3): 重构example vol3~7目录和在线源码接入 - 14 篇 OnlineCompilerDemo 配齐(补 map、重写 initializer、新建 8 个) - vol34567 拆成 vol3/vol4/vol5/vol6/vol7,vol3 重新连续编号 01-14 - 同步更新所有 sourcePath(含 EN) * feat(i18n): 同步英文翻译:vol3 在线源码接入+目录拆分 - 25 个文件重译(glm-4.6),vol3 14 篇 EN 齐全含 OnlineCompilerDemo - EN source-path 同步到 code/examples/vol3-7 新结构 - EN vol3 index 升级到 14 篇逻辑顺序 * chore: 全仓 reading_time 补全 + frontmatter 规范化 - check_quality --fix 补全 reading_time_minutes + frontmatter 字母序规范化 - 修 vol3 deque/map 的 internal_link 缺 .md(4 处 CN+EN) - EN 翻译同步 25 文件# Please enter the commit message for your changes. Lines starting
1 parent 84e12e5 commit 51ea44a

726 files changed

Lines changed: 13961 additions & 11568 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
---
2020

2121
<!-- COVERAGE_START -->
22-
![English Coverage](https://img.shields.io/badge/en_coverage-100%25-green.svg) 433/433 docs translated
22+
![English Coverage](https://img.shields.io/badge/en_coverage-100%25-green.svg) 439/439 docs translated
2323
<!-- COVERAGE_END -->
2424

2525
## 这是什么项目
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Standard: C++20
2+
// 容器选择:演示「按操作选容器」——按位置存 vs 按键查,呼应选择决策树
3+
#include <iostream>
4+
#include <list>
5+
#include <map>
6+
#include <unordered_map>
7+
#include <vector>
8+
9+
int main() {
10+
std::cout << "== 按位置存:顺序容器,关心在哪插删 ==\n";
11+
std::vector<int> v;
12+
for (int i = 0; i < 5; ++i) {
13+
v.push_back(i); // 尾部摊还 O(1)
14+
}
15+
std::list<int> lt;
16+
for (int i = 0; i < 5; ++i) {
17+
lt.push_front(i); // 头部 O(1)
18+
}
19+
std::cout << "vector 尾插 5 个(尾部摊还 O(1)),list 头插 5 个(头部 O(1))\n";
20+
std::cout << "→ 频繁头尾进出用 deque,主要尾部增长用 vector(务必 reserve)\n";
21+
22+
std::cout << "\n== 按键查:关联容器,关心按什么查 ==\n";
23+
constexpr int N = 100'000;
24+
std::map<int, int> om;
25+
std::unordered_map<int, int> um;
26+
for (int i = 0; i < N; ++i) {
27+
om[i] = i;
28+
um[i] = i;
29+
}
30+
std::cout << "map.find(N/2) 命中: " << (om.find(N / 2) != om.end())
31+
<< "(O(log n) 红黑树,可有序遍历)\n";
32+
std::cout << "unordered_map.find(N/2) 命中: " << (um.find(N / 2) != um.end())
33+
<< "(平均 O(1) 哈希,最快)\n";
34+
std::cout << "→ 要有序遍历用 map,只要快查用 unordered(记得 reserve)\n";
35+
36+
std::cout << "\n== 决策三问(挑容器先问这三件事)==\n";
37+
std::cout << "1) 大小编译期已知且不变?→ array\n";
38+
std::cout << "2) 按键查找?→ 有序遍历用 map/set,否则 unordered(平均 O(1))\n";
39+
std::cout << "3) 按位置存?→ 头尾用 deque,尾部用 vector,已知位置频繁增删用 list\n";
40+
std::cout << "拿不准就 vector:连续、尾部摊还 O(1)、接口最全,覆盖面最广的安全牌\n";
41+
return 0;
42+
}
File renamed without changes.
File renamed without changes.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Standard: C++20
2+
// deque / list / forward_list:vector 之外的三个选择——头插都 O(1),但内存布局与 splice 各异
3+
#include <deque>
4+
#include <forward_list>
5+
#include <iostream>
6+
#include <list>
7+
8+
int main() {
9+
std::cout << "== 三者头插都 O(1),但存储布局不同 ==\n";
10+
constexpr int N = 100'000;
11+
12+
std::deque<int> dq;
13+
for (int i = 0; i < N; ++i) {
14+
dq.push_front(i); // 分段连续,头尾均 O(1)
15+
}
16+
17+
std::list<int> lt;
18+
for (int i = 0; i < N; ++i) {
19+
lt.push_front(i); // 双向链表节点
20+
}
21+
22+
std::forward_list<int> fl;
23+
for (int i = 0; i < N; ++i) {
24+
fl.push_front(i); // 单向链表,最省内存(无 prev 指针)
25+
}
26+
std::cout << "各头插 " << N << " 个,复杂度都是 O(1)\n";
27+
28+
std::cout << "\n== sizeof:forward_list 最省,deque 有分段控制开销 ==\n";
29+
std::cout << "sizeof(deque<int>) = " << sizeof(dq) << '\n';
30+
std::cout << "sizeof(list<int>) = " << sizeof(lt) << '\n';
31+
std::cout << "sizeof(forward_list<int>) = " << sizeof(fl) << '\n';
32+
33+
std::cout << "\n== list::splice:O(1) 把整串节点搬过来,零拷贝 ==\n";
34+
std::list<int> a{1, 2, 3};
35+
std::list<int> b{10, 20};
36+
auto it = a.begin();
37+
++it; // 指向元素 2
38+
a.splice(it, b); // 把 b 整个接到 a 的 it 之前,搬节点不拷贝
39+
std::cout << "splice 后 a = ";
40+
for (auto x : a) {
41+
std::cout << x << ' ';
42+
}
43+
std::cout << "\nb 现在 size = " << b.size() << "(节点被搬走,b 空了)\n";
44+
45+
std::cout << "\n== forward_list 没有 size():单向链表数元素要 O(n) ==\n";
46+
int cnt = 0;
47+
for (auto x : fl) {
48+
(void)x;
49+
++cnt;
50+
}
51+
std::cout << "forward_list 手动数 = " << cnt << '\n';
52+
return 0;
53+
}

code/examples/vol3/06_map_set.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Standard: C++20
2+
// map / set:底层红黑树按键有序、异构查找(transparent 比较器,string_view 直接查)、extract
3+
// 节点搬家
4+
#include <iostream>
5+
#include <map>
6+
#include <string>
7+
#include <string_view>
8+
9+
int main() {
10+
std::cout << "== map 底层红黑树:按键自动有序 ==\n";
11+
std::map<int, std::string> m;
12+
m[3] = "three";
13+
m[1] = "one";
14+
m[2] = "two";
15+
std::cout << "插入 3,1,2 后遍历(自动有序):";
16+
for (const auto& [k, v] : m) {
17+
std::cout << k << ':' << v << ' ';
18+
}
19+
std::cout << '\n';
20+
21+
std::cout << "\n== 异构查找:用 string_view 查 string 的 map,免构造临时 string ==\n";
22+
std::map<std::string, int, std::less<>> sm; // std::less<> = 透明比较器
23+
sm["apple"] = 1;
24+
sm["banana"] = 2;
25+
std::string_view key = "banana";
26+
auto it = sm.find(key); // string_view 直接查,不构造临时 string
27+
if (it != sm.end()) {
28+
std::cout << "find(string_view) 命中: " << it->second << '\n';
29+
}
30+
std::cout << "(用 std::less<> 而非 std::less<std::string>,比较器才支持异构 key)\n";
31+
32+
std::cout << "\n== extract:把节点从一棵 map 搬到另一棵,零拷贝 ==\n";
33+
std::map<int, std::string> a{{1, "one"}, {2, "two"}};
34+
std::map<int, std::string> b;
35+
auto node = a.extract(1); // 抽出节点(连带 string,不拷贝)
36+
b.insert(std::move(node)); // 接到 b
37+
std::cout << "extract(1) 后 a.size = " << a.size() << ", b.size = " << b.size() << '\n';
38+
std::cout << "(extract 搬节点不拷贝 string,适合改 key、换分配器、跨 map 转移)\n";
39+
40+
std::cout << "\n== 复杂度:查找/插入/删除均 O(log n) ==\n";
41+
std::cout << "要有序遍历用 map/set;只要平均 O(1) 查找用 unordered 版\n";
42+
return 0;
43+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Standard: C++20
2+
// unordered_map:哈希桶、rehash 触发的质数桶序列、load_factor、reserve 预撑桶
3+
#include <iostream>
4+
#include <unordered_map>
5+
6+
int main() {
7+
std::cout << "== rehash 触发质数桶序列(bucket_count 跳变)==\n";
8+
std::unordered_map<int, int> m;
9+
std::size_t last = m.bucket_count();
10+
std::cout << "初始 bucket_count = " << last << '\n';
11+
for (int i = 0; i < 200; ++i) {
12+
m[i] = i;
13+
if (m.bucket_count() != last) {
14+
std::cout << "插入 " << i << " 后 rehash: " << last << " -> " << m.bucket_count()
15+
<< "(load_factor=" << m.load_factor() << "\n";
16+
last = m.bucket_count();
17+
}
18+
}
19+
20+
std::cout << "\n== 桶分布:看元素怎么落桶(链地址法)==\n";
21+
std::unordered_map<int, int> small;
22+
for (int i = 0; i < 10; ++i) {
23+
small[i] = i;
24+
}
25+
int non_empty = 0;
26+
for (std::size_t b = 0; b < small.bucket_count(); ++b) {
27+
if (small.bucket_size(b) > 0) {
28+
++non_empty;
29+
std::cout << "bucket " << b << "" << small.bucket_size(b) << " 个元素\n";
30+
}
31+
}
32+
std::cout << "" << small.bucket_count() << " 个桶," << non_empty << " 个非空\n";
33+
std::cout << "max_load_factor = " << small.max_load_factor()
34+
<< "(默认 1.0,平均每桶元素数超了就 rehash)\n";
35+
36+
std::cout << "\n== reserve 预撑桶,避免 hot path 里反复 rehash ==\n";
37+
std::unordered_map<int, int> reserved;
38+
reserved.reserve(1000); // 内部按 max_load_factor 算出足够的桶
39+
std::cout << "reserve(1000) 后 bucket_count = " << reserved.bucket_count() << '\n';
40+
return 0;
41+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Standard: C++20
2+
// 容器适配器:stack(LIFO) / queue(FIFO) / priority_queue(堆)——priority_queue 默认最大堆,greater
3+
// 变最小堆
4+
#include <functional>
5+
#include <iostream>
6+
#include <queue>
7+
#include <stack>
8+
#include <vector>
9+
10+
int main() {
11+
std::cout << "== stack:LIFO,top/push/pop 全在 back 一端 ==\n";
12+
std::stack<int> s;
13+
for (int x : {1, 2, 3}) {
14+
s.push(x);
15+
}
16+
std::cout << "push 1,2,3 后,top = " << s.top() << "(最后进的先出)\n";
17+
18+
std::cout << "\n== queue:FIFO,push 在 back、front/pop 在 front ==\n";
19+
std::queue<int> q;
20+
for (int x : {1, 2, 3}) {
21+
q.push(x);
22+
}
23+
std::cout << "push 1,2,3 后,front = " << q.front() << " back = " << q.back() << '\n';
24+
25+
std::cout << "\n== priority_queue 默认最大堆(vector + less)==\n";
26+
std::priority_queue<int> pq;
27+
for (int x : {5, 1, 9, 3, 7}) {
28+
pq.push(x);
29+
}
30+
std::cout << "依次 pop: ";
31+
while (!pq.empty()) {
32+
std::cout << pq.top() << ' ';
33+
pq.pop();
34+
}
35+
std::cout << '\n';
36+
37+
std::cout << "\n== 换 greater 变最小堆 ==\n";
38+
std::priority_queue<int, std::vector<int>, std::greater<int>> min_pq;
39+
for (int x : {5, 1, 9, 3, 7}) {
40+
min_pq.push(x);
41+
}
42+
std::cout << "依次 pop: ";
43+
while (!min_pq.empty()) {
44+
std::cout << min_pq.top() << ' ';
45+
min_pq.pop();
46+
}
47+
std::cout << '\n';
48+
49+
std::cout << "\n== 复杂度:top O(1),push/pop O(log n) ==\n";
50+
std::cout << "(push = push_back + push_heap;pop = pop_heap + pop_back;底层就是堆算法)\n";
51+
return 0;
52+
}

0 commit comments

Comments
 (0)