Compare commits
9 commits
5f8a472ed0
...
934256ae4f
Author | SHA1 | Date | |
---|---|---|---|
|
934256ae4f | ||
|
4db5c19011 | ||
|
356cc35e8a | ||
|
dad0a3fd95 | ||
|
e41b0a3156 | ||
|
b6939da46c | ||
|
abf1f115bf | ||
|
6348dbe18d | ||
|
ca774eefbf |
5
.gitignore
vendored
|
@ -1,7 +1,7 @@
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Editor
|
# editors
|
||||||
.vscode/
|
.vscode/
|
||||||
**/.idea
|
**/.idea
|
||||||
|
|
||||||
|
@ -12,6 +12,3 @@
|
||||||
/build
|
/build
|
||||||
/site
|
/site
|
||||||
/utils
|
/utils
|
||||||
|
|
||||||
# test script
|
|
||||||
test.sh
|
|
||||||
|
|
|
@ -111,16 +111,29 @@ int popLast(ArrayDeque *deque) {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 返回数组用于打印 */
|
||||||
|
int *toArray(ArrayDeque *deque, int *queSize) {
|
||||||
|
*queSize = deque->queSize;
|
||||||
|
int *res = (int *)calloc(deque->queSize, sizeof(int));
|
||||||
|
int j = deque->front;
|
||||||
|
for (int i = 0; i < deque->queSize; i++) {
|
||||||
|
res[i] = deque->nums[j % deque->queCapacity];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
int main() {
|
int main() {
|
||||||
/* 初始化队列 */
|
/* 初始化队列 */
|
||||||
int capacity = 10;
|
int capacity = 10;
|
||||||
|
int queSize;
|
||||||
ArrayDeque *deque = newArrayDeque(capacity);
|
ArrayDeque *deque = newArrayDeque(capacity);
|
||||||
pushLast(deque, 3);
|
pushLast(deque, 3);
|
||||||
pushLast(deque, 2);
|
pushLast(deque, 2);
|
||||||
pushLast(deque, 5);
|
pushLast(deque, 5);
|
||||||
printf("双向队列 deque = ");
|
printf("双向队列 deque = ");
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
|
|
||||||
/* 访问元素 */
|
/* 访问元素 */
|
||||||
int peekFirstNum = peekFirst(deque);
|
int peekFirstNum = peekFirst(deque);
|
||||||
|
@ -131,18 +144,18 @@ int main() {
|
||||||
/* 元素入队 */
|
/* 元素入队 */
|
||||||
pushLast(deque, 4);
|
pushLast(deque, 4);
|
||||||
printf("元素 4 队尾入队后 deque = ");
|
printf("元素 4 队尾入队后 deque = ");
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
pushFirst(deque, 1);
|
pushFirst(deque, 1);
|
||||||
printf("元素 1 队首入队后 deque = ");
|
printf("元素 1 队首入队后 deque = ");
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
|
|
||||||
/* 元素出队 */
|
/* 元素出队 */
|
||||||
int popLastNum = popLast(deque);
|
int popLastNum = popLast(deque);
|
||||||
printf("队尾出队元素 = %d ,队尾出队后 deque= ", popLastNum);
|
printf("队尾出队元素 = %d ,队尾出队后 deque= ", popLastNum);
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
int popFirstNum = popFirst(deque);
|
int popFirstNum = popFirst(deque);
|
||||||
printf("队首出队元素 = %d ,队首出队后 deque= ", popFirstNum);
|
printf("队首出队元素 = %d ,队首出队后 deque= ", popFirstNum);
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
|
|
||||||
/* 获取队列的长度 */
|
/* 获取队列的长度 */
|
||||||
int dequeSize = size(deque);
|
int dequeSize = size(deque);
|
||||||
|
@ -156,4 +169,4 @@ int main() {
|
||||||
delArrayDeque(deque);
|
delArrayDeque(deque);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -74,10 +74,23 @@ int pop(ArrayQueue *queue) {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 返回数组用于打印 */
|
||||||
|
int *toArray(ArrayQueue *queue, int *queSize) {
|
||||||
|
*queSize = queue->queSize;
|
||||||
|
int *res = (int *)calloc(queue->queSize, sizeof(int));
|
||||||
|
int j = queue->front;
|
||||||
|
for (int i = 0; i < queue->queSize; i++) {
|
||||||
|
res[i] = queue->nums[j % queue->queCapacity];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
int main() {
|
int main() {
|
||||||
/* 初始化队列 */
|
/* 初始化队列 */
|
||||||
int capacity = 10;
|
int capacity = 10;
|
||||||
|
int queSize;
|
||||||
ArrayQueue *queue = newArrayQueue(capacity);
|
ArrayQueue *queue = newArrayQueue(capacity);
|
||||||
|
|
||||||
/* 元素入队 */
|
/* 元素入队 */
|
||||||
|
@ -87,7 +100,7 @@ int main() {
|
||||||
push(queue, 5);
|
push(queue, 5);
|
||||||
push(queue, 4);
|
push(queue, 4);
|
||||||
printf("队列 queue = ");
|
printf("队列 queue = ");
|
||||||
printArray(queue->nums, queue->queSize);
|
printArray(toArray(queue, &queSize), queSize);
|
||||||
|
|
||||||
/* 访问队首元素 */
|
/* 访问队首元素 */
|
||||||
int peekNum = peek(queue);
|
int peekNum = peek(queue);
|
||||||
|
@ -96,7 +109,7 @@ int main() {
|
||||||
/* 元素出队 */
|
/* 元素出队 */
|
||||||
peekNum = pop(queue);
|
peekNum = pop(queue);
|
||||||
printf("出队元素 pop = %d ,出队后 queue = ", peekNum);
|
printf("出队元素 pop = %d ,出队后 queue = ", peekNum);
|
||||||
printArray(queue->nums, queue->queSize);
|
printArray(toArray(queue, &queSize), queSize);
|
||||||
|
|
||||||
/* 获取队列的长度 */
|
/* 获取队列的长度 */
|
||||||
int queueSize = size(queue);
|
int queueSize = size(queue);
|
||||||
|
@ -111,11 +124,11 @@ int main() {
|
||||||
push(queue, i);
|
push(queue, i);
|
||||||
pop(queue);
|
pop(queue);
|
||||||
printf("第 %d 轮入队 + 出队后 queue = ", i);
|
printf("第 %d 轮入队 + 出队后 queue = ", i);
|
||||||
printArray(queue->nums, queue->queSize);
|
printArray(toArray(queue, &queSize), queSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放内存
|
// 释放内存
|
||||||
delArrayQueue(queue);
|
delArrayQueue(queue);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
@ -71,6 +71,16 @@
|
||||||
|
|
||||||
另一方面,必要使用链表的情况主要是二叉树和图。栈和队列往往会使用编程语言提供的 `stack` 和 `queue` ,而非链表。
|
另一方面,必要使用链表的情况主要是二叉树和图。栈和队列往往会使用编程语言提供的 `stack` 和 `queue` ,而非链表。
|
||||||
|
|
||||||
**Q**:初始化列表 `res = [0] * self.size()` 操作,会导致 `res` 的每个元素引用相同的地址吗?
|
**Q**:操作 `res = [[0]] * n` 生成了一个二维列表,其中每一个 `[0]` 都是独立的吗?
|
||||||
|
|
||||||
不会。但二维数组会有这个问题,例如初始化二维列表 `res = [[0]] * self.size()` ,则多次引用了同一个列表 `[0]` 。
|
不是独立的。此二维列表中,所有的 `[0]` 实际上是同一个对象的引用。如果我们修改其中一个元素,会发现所有的对应元素都会随之改变。
|
||||||
|
|
||||||
|
如果希望二维列表中的每个 `[0]` 都是独立的,可以使用 `res = [[0] for _ in range(n)]` 来实现。这种方式的原理是初始化了 $n$ 个独立的 `[0]` 列表对象。
|
||||||
|
|
||||||
|
**Q**:操作 `res = [0] * n` 生成了一个列表,其中每一个整数 0 都是独立的吗?
|
||||||
|
|
||||||
|
在该列表中,所有整数 0 都是同一个对象的引用。这是因为 Python 对小整数(通常是 -5 到 256)采用了缓存池机制,以便最大化对象复用,从而提升性能。
|
||||||
|
|
||||||
|
虽然它们指向同一个对象,但我们仍然可以独立修改列表中的每个元素,这是因为 Python 的整数是“不可变对象”。当我们修改某个元素时,实际上是切换为另一个对象的引用,而不是改变原有对象本身。
|
||||||
|
|
||||||
|
然而,当列表元素是“可变对象”时(例如列表、字典或类实例等),修改某个元素会直接改变该对象本身,所有引用该对象的元素都会产生相同变化。
|
||||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -1120,7 +1120,7 @@ $$
|
||||||
|
|
||||||
生物学的“细胞分裂”是指数阶增长的典型例子:初始状态为 $1$ 个细胞,分裂一轮后变为 $2$ 个,分裂两轮后变为 $4$ 个,以此类推,分裂 $n$ 轮后有 $2^n$ 个细胞。
|
生物学的“细胞分裂”是指数阶增长的典型例子:初始状态为 $1$ 个细胞,分裂一轮后变为 $2$ 个,分裂两轮后变为 $4$ 个,以此类推,分裂 $n$ 轮后有 $2^n$ 个细胞。
|
||||||
|
|
||||||
下图和以下代码模拟了细胞分裂的过程,时间复杂度为 $O(2^n)$ :
|
下图和以下代码模拟了细胞分裂的过程,时间复杂度为 $O(2^n)$ 。请注意,输入 $n$ 表示分裂轮数,返回值 `count` 表示总分裂次数。
|
||||||
|
|
||||||
```src
|
```src
|
||||||
[file]{time_complexity}-[class]{}-[func]{exponential}
|
[file]{time_complexity}-[class]{}-[func]{exponential}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
- 整理扑克的过程与插入排序算法非常类似。插入排序算法适合排序小型数据集。
|
- 整理扑克的过程与插入排序算法非常类似。插入排序算法适合排序小型数据集。
|
||||||
- 货币找零的步骤本质上是贪心算法,每一步都采取当前看来最好的选择。
|
- 货币找零的步骤本质上是贪心算法,每一步都采取当前看来最好的选择。
|
||||||
- 算法是在有限时间内解决特定问题的一组指令或操作步骤,而数据结构是计算机中组织和存储数据的方式。
|
- 算法是在有限时间内解决特定问题的一组指令或操作步骤,而数据结构是计算机中组织和存储数据的方式。
|
||||||
- 数据结构与算法紧密相连。数据结构是算法的基石,而算法是数据结构发挥作用的舞台。
|
- 数据结构与算法紧密相连。数据结构是算法的基石,而算法为数据结构注入生命力。
|
||||||
- 我们可以将数据结构与算法类比为拼装积木,积木代表数据,积木的形状和连接方式等代表数据结构,拼装积木的步骤则对应算法。
|
- 我们可以将数据结构与算法类比为拼装积木,积木代表数据,积木的形状和连接方式等代表数据结构,拼装积木的步骤则对应算法。
|
||||||
|
|
||||||
### Q & A
|
### Q & A
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
如下图所示,数据结构与算法高度相关、紧密结合,具体表现在以下三个方面。
|
如下图所示,数据结构与算法高度相关、紧密结合,具体表现在以下三个方面。
|
||||||
|
|
||||||
- 数据结构是算法的基石。数据结构为算法提供了结构化存储的数据,以及操作数据的方法。
|
- 数据结构是算法的基石。数据结构为算法提供了结构化存储的数据,以及操作数据的方法。
|
||||||
- 算法是数据结构发挥作用的舞台。数据结构本身仅存储数据信息,结合算法才能解决特定问题。
|
- 算法为数据结构注入生命力。数据结构本身仅存储数据信息,结合算法才能解决特定问题。
|
||||||
- 算法通常可以基于不同的数据结构实现,但执行效率可能相差很大,选择合适的数据结构是关键。
|
- 算法通常可以基于不同的数据结构实现,但执行效率可能相差很大,选择合适的数据结构是关键。
|
||||||
|
|
||||||
![数据结构与算法的关系](what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png)
|
![数据结构与算法的关系](what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png)
|
||||||
|
|
|
@ -30,9 +30,9 @@
|
||||||
|
|
||||||
## 致谢
|
## 致谢
|
||||||
|
|
||||||
本书在开源社区众多贡献者的共同努力下不断完善。感谢每一位投入时间与精力的撰稿人,他们是(按照 GitHub 自动生成的顺序):krahets、Gonglja、nuomi1、codingonion、Reanon、justin-tse、hpstory、danielsss、curtishd、night-cruise、S-N-O-R-L-A-X、msk397、gvenusleo、RiverTwilight、gyt95、zhuoqinyue、Zuoxun、mingXta、hello-ikun、khoaxuantu、FangYuan33、GN-Yu、longsizhuo、mgisr、Cathay-Chen、guowei-gong、xBLACKICEx、K3v123、IsChristina、JoseHung、qualifier1024、pengchzn、Guanngxu、QiLOL、L-Super、WSL0809、Slone123c、lhxsm、yuan0221、what-is-me、rongyi、JeffersonHuang、longranger2、theNefelibatas、yuelinxin、xiongsp、nanlei、a16su、cy-by-side、gaofer、malone6、Wonderdch、hongyun-robot、XiaChuerwu、yd-j、bluebean-cloud、iron-irax、he-weilai、Nigh、MolDuM、Phoenix0415、XC-Zero、SamJin98、reeswell、NI-SW、Horbin-Magician、xjr7670、YangXuanyi、DullSword、iStig、qq909244296、jiaxianhua、wenjianmin、keshida、kilikilikid、lclc6、lwbaptx、luluxia、boloboloda、hts0000、gledfish、fbigm、echo1937、szu17dmy、dshlstarr、coderlef、czruby、beintentional、KeiichiKasai、xb534、ElaBosak233、baagod、zhouLion、yishangzhang、yi427、yabo083、weibk、wangwang105、th1nk3r-ing、tao363、4yDX3906、syd168、siqyka、selear、sdshaoda、noobcodemaker、chadyi、lyl625760、lucaswangdev、liuxjerry、0130w、shanghai-Jerry、JackYang-hellobobo、Javesun99、lipusheng、ShiMaRing、FreddieLi、FloranceYeh、Transmigration-zhou、fanchenggang、gltianwen、Dr-XYZ、curly210102、CuB3y0nd、youshaoXG、bubble9um、fanenr、52coder、foursevenlove、KorsChen、ZongYangL、hezhizhen、linzeyan、ZJKung、GaochaoZhu、yang-le、Evilrabbit520、Turing-1024-Lee、Suremotoo、Allen-Scai、Richard-Zhang1019、qingpeng9802、primexiao、nidhoggfgg、1ch0、MwumLi、ZnYang2018、hugtyftg、logan-qiu、psychelzh 和 Keynman 。
|
本书在开源社区众多贡献者的共同努力下不断完善。感谢每一位投入时间与精力的撰稿人,他们是(按照 GitHub 自动生成的顺序):krahets、coderonion、Gonglja、nuomi1、Reanon、justin-tse、hpstory、danielsss、curtishd、night-cruise、S-N-O-R-L-A-X、msk397、gvenusleo、khoaxuantu、RiverTwilight、rongyi、gyt95、zhuoqinyue、K3v123、Zuoxun、mingXta、hello-ikun、FangYuan33、GN-Yu、yuelinxin、longsizhuo、Cathay-Chen、guowei-gong、xBLACKICEx、IsChristina、JoseHung、qualifier1024、QiLOL、pengchzn、Guanngxu、L-Super、WSL0809、Slone123c、lhxsm、yuan0221、what-is-me、theNefelibatas、longranger2、cy-by-side、xiongsp、JeffersonHuang、Transmigration-zhou、magentaqin、Wonderdch、malone6、xiaomiusa87、gaofer、bluebean-cloud、a16su、Shyam-Chen、nanlei、hongyun-robot、Phoenix0415、MolDuM、Nigh、he-weilai、junminhong、mgisr、iron-irax、yd-j、XiaChuerwu、XC-Zero、seven1240、SamJin98、wodray、reeswell、NI-SW、Horbin-Magician、Enlightenus、xjr7670、YangXuanyi、DullSword、boloboloda、iStig、qq909244296、jiaxianhua、wenjianmin、keshida、kilikilikid、lclc6、lwbaptx、liuxjerry、lucaswangdev、lyl625760、hts0000、gledfish、fbigm、echo1937、szu17dmy、dshlstarr、Yucao-cy、coderlef、czruby、bongbongbakudan、beintentional、ZongYangL、ZhongYuuu、luluxia、xb534、bitsmi、ElaBosak233、baagod、zhouLion、yishangzhang、yi427、yabo083、weibk、wangwang105、th1nk3r-ing、tao363、4yDX3906、syd168、steventimes、sslmj2020、smilelsb、siqyka、selear、sdshaoda、Xi-Row、popozhu、nuquist19、noobcodemaker、XiaoK29、chadyi、ZhongGuanbin、shanghai-Jerry、JackYang-hellobobo、Javesun99、lipusheng、BlindTerran、ShiMaRing、FreddieLi、FloranceYeh、iFleey、fanchenggang、gltianwen、goerll、Dr-XYZ、nedchu、curly210102、CuB3y0nd、KraHsu、CarrotDLaw、youshaoXG、bubble9um、fanenr、eagleanurag、LifeGoesOnionOnionOnion、52coder、foursevenlove、KorsChen、hezhizhen、linzeyan、ZJKung、GaochaoZhu、hopkings2008、yang-le、Evilrabbit520、Turing-1024-Lee、thomasq0、Suremotoo、Allen-Scai、Risuntsy、Richard-Zhang1019、qingpeng9802、primexiao、nidhoggfgg、1ch0、MwumLi、martinx、ZnYang2018、hugtyftg、logan-qiu、psychelzh、Keynman、KeiichiKasai 和 0130w。
|
||||||
|
|
||||||
本书的代码审阅工作由 codingonion、curtishd、Gonglja、gvenusleo、hpstory、justin-tse、khoaxuantu、krahets、night-cruise、nuomi1 和 Reanon 完成(按照首字母顺序排列)。感谢他们付出的时间与精力,正是他们确保了各语言代码的规范与统一。
|
本书的代码审阅工作由 coderonion、curtishd、Gonglja、gvenusleo、hpstory、justin-tse、khoaxuantu、krahets、night-cruise、nuomi1、Reanon 和 rongyi 完成(按照首字母顺序排列)。感谢他们付出的时间与精力,正是他们确保了各语言代码的规范与统一。
|
||||||
|
|
||||||
在本书的创作过程中,我得到了许多人的帮助。
|
在本书的创作过程中,我得到了许多人的帮助。
|
||||||
|
|
||||||
|
|
|
@ -258,9 +258,9 @@
|
||||||
<h3>代码审阅者</h3>
|
<h3>代码审阅者</h3>
|
||||||
<div class="profile-div">
|
<div class="profile-div">
|
||||||
<div class="profile-cell">
|
<div class="profile-cell">
|
||||||
<a href="https://github.com/codingonion">
|
<a href="https://github.com/coderonion">
|
||||||
<img class="profile-img" src="assets/avatar/avatar_codingonion.jpg" alt="Reviewer: codingonion" />
|
<img class="profile-img" src="assets/avatar/avatar_coderonion.jpg" alt="Reviewer: coderonion" />
|
||||||
<br><b>codingonion</b>
|
<br><b>coderonion</b>
|
||||||
<br><sub>Zig, Rust</sub>
|
<br><sub>Zig, Rust</sub>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,14 +32,14 @@ That is, our contributors are computer scientists, engineers, and students from
|
||||||
> [!important]
|
> [!important]
|
||||||
> Before diving in, ensure you're comfortable with the GitHub pull request workflow and have read the "Translation standards" and "Pseudo-code for translation" below.
|
> Before diving in, ensure you're comfortable with the GitHub pull request workflow and have read the "Translation standards" and "Pseudo-code for translation" below.
|
||||||
|
|
||||||
1. **Self-assignment**: Visit [GitHub projects](https://github.com/users/krahets/projects/2/views/4) to select an unclaimed task and mark it as `In Progress`.
|
1. **Task assignment**: Self-assign a task in the Notion workspace.
|
||||||
2. **Translation**: We encourage preserving the original meaning while ensuring the translation is natural and fluent.
|
2. **Translation**: Optimize the translation on your local PC, referring to the “Translation Pseudo-Code” section below for more details.
|
||||||
3. **Peer review**: Please carefully check your changes before submitting a Pull Request (PR). After approval by two reviewers, it will be merged into the project.
|
3. **Peer review**: Carefully review your changes before submitting a Pull Request (PR). The PR will be merged into the main branch after approval from two reviewers.
|
||||||
|
|
||||||
## Translation standards
|
## Translation standards
|
||||||
|
|
||||||
> [!tip]
|
> [!tip]
|
||||||
> The "Accuracy" and "Authenticity" are primarily handled by native Chinese speakers and native English speakers, respectively.
|
> **The "Accuracy" and "Authenticity" are primarily handled by native Chinese speakers and native English speakers, respectively.**
|
||||||
>
|
>
|
||||||
> In some instances, "Accuracy (consistency)" and "Authenticity" represent a trade-off, where optimizing one aspect could significantly affect the other. In such cases, please leave a comment in the pull request for discussion.
|
> In some instances, "Accuracy (consistency)" and "Authenticity" represent a trade-off, where optimizing one aspect could significantly affect the other. In such cases, please leave a comment in the pull request for discussion.
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
|
@ -2,30 +2,30 @@
|
||||||
|
|
||||||
### Key review
|
### Key review
|
||||||
|
|
||||||
- A graph consists of vertices and edges and can be represented as a set comprising a group of vertices and a group of edges.
|
- A graph is made up of vertices and edges. It can be described as a set of vertices and a set of edges.
|
||||||
- Compared to linear relationships (linked lists) and divide-and-conquer relationships (trees), network relationships (graphs) have a higher degree of freedom and are therefore more complex.
|
- Compared to linear relationships (like linked lists) and hierarchical relationships (like trees), network relationships (graphs) offer greater flexibility, making them more complex.
|
||||||
- The edges of a directed graph have directionality, any vertex in a connected graph is reachable, and each edge in a weighted graph contains a weight variable.
|
- In a directed graph, edges have directions. In a connected graph, any vertex can be reached from any other vertex. In a weighted graph, each edge has an associated weight variable.
|
||||||
- Adjacency matrices use matrices to represent graphs, with each row (column) representing a vertex and matrix elements representing edges, using $1$ or $0$ to indicate the presence or absence of an edge between two vertices. Adjacency matrices are highly efficient for add, delete, find, and modify operations, but they consume more space.
|
- An adjacency matrix is a way to represent a graph using matrix (2D array). The rows and columns represent the vertices. The matrix element value indicates whether there is an edge between two vertices, using $1$ for an edge or $0$ for no edge. Adjacency matrices are highly efficient for operations like adding, deleting, or checking edges, but they require more space.
|
||||||
- Adjacency lists use multiple linked lists to represent graphs, with the $i^{th}$ list corresponding to vertex $i$, containing all its adjacent vertices. Adjacency lists save more space compared to adjacency matrices, but since it is necessary to traverse the list to find edges, their time efficiency is lower.
|
- An adjacency list is another common way to represent a graph using a collection of linked lists. Each vertex in the graph has a list that contains all its adjacent vertices. The $i^{th}$ list represents vertex $i$. Adjacency lists use less space compared to adjacency matrices. However, since it requires traversing the list to find edges, the time efficiency is lower.
|
||||||
- When the linked lists in the adjacency list are too long, they can be converted into red-black trees or hash tables to improve query efficiency.
|
- When the linked lists in an adjacency list are long enough, they can be converted into red-black trees or hash tables to improve lookup efficiency.
|
||||||
- From the perspective of algorithmic thinking, adjacency matrices embody the principle of "space for time," while adjacency lists embody "time for space."
|
- From the perspective of algorithmic design, an adjacency matrix reflects the concept of "trading space for time", whereas an adjacency list reflects "trading time for space".
|
||||||
- Graphs can be used to model various real systems, such as social networks, subway routes, etc.
|
- Graphs can be used to model various real-world systems, such as social networks, subway routes.
|
||||||
- A tree is a special case of a graph, and tree traversal is also a special case of graph traversal.
|
- A tree is a special case of a graph, and tree traversal is also a special case of graph traversal.
|
||||||
- Breadth-first traversal of a graph is a search method that expands layer by layer from near to far, usually implemented with a queue.
|
- Breadth-first traversal of a graph is a search method that expands layer by layer from near to far, typically using a queue.
|
||||||
- Depth-first traversal of a graph is a search method that prefers to go as deep as possible and backtracks when no further paths are available, often based on recursion.
|
- Depth-first traversal of a graph is a search method that prioritizes reaching the end before backtracking when no further path is available. It is often implemented using recursion.
|
||||||
|
|
||||||
### Q & A
|
### Q & A
|
||||||
|
|
||||||
**Q**: Is a path defined as a sequence of vertices or a sequence of edges?
|
**Q**: Is a path defined as a sequence of vertices or a sequence of edges?
|
||||||
|
|
||||||
Definitions vary between different language versions on Wikipedia: the English version defines a path as "a sequence of edges," while the Chinese version defines it as "a sequence of vertices." Here is the original text from the English version: In graph theory, a path in a graph is a finite or infinite sequence of edges which joins a sequence of vertices.
|
In graph theory, a path in a graph is a finite or infinite sequence of edges which joins a sequence of vertices.
|
||||||
|
|
||||||
In this document, a path is considered a sequence of edges, rather than a sequence of vertices. This is because there might be multiple edges connecting two vertices, in which case each edge corresponds to a path.
|
In this document, a path is considered a sequence of edges, rather than a sequence of vertices. This is because there might be multiple edges connecting two vertices, in which case each edge corresponds to a path.
|
||||||
|
|
||||||
**Q**: In a disconnected graph, are there points that cannot be traversed to?
|
**Q**: In a disconnected graph, are there points that cannot be traversed?
|
||||||
|
|
||||||
In a disconnected graph, starting from a certain vertex, there is at least one vertex that cannot be reached. Traversing a disconnected graph requires setting multiple starting points to traverse all connected components of the graph.
|
In a disconnected graph, there is at least one vertex that cannot be reached from a specific point. To traverse a disconnected graph, you need to set multiple starting points to traverse all the connected components of the graph.
|
||||||
|
|
||||||
**Q**: In an adjacency list, does the order of "all vertices connected to that vertex" matter?
|
**Q**: In an adjacency list, does the order of "all vertices connected to that vertex" matter?
|
||||||
|
|
||||||
It can be in any order. However, in practical applications, it might be necessary to sort according to certain rules, such as the order in which vertices are added, or the order of vertex values, etc., to facilitate the quick search for vertices with certain extremal values.
|
It can be in any order. However, in real-world applications, it might be necessary to sort them according to certain rules, such as the order in which vertices are added, or the order of vertex values. This can help find vertices quickly with certain extreme values.
|
||||||
|
|
|
@ -30,9 +30,9 @@ The main content of the book is shown in the figure below.
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
|
|
||||||
This book is continuously improved with the joint efforts of many contributors from the open-source community. Thanks to each writer who invested their time and energy, listed in the order generated by GitHub: krahets, codingonion, nuomi1, Gonglja, Reanon, justin-tse, danielsss, hpstory, S-N-O-R-L-A-X, night-cruise, msk397, gvenusleo, RiverTwilight, gyt95, zhuoqinyue, Zuoxun, Xia-Sang, mingXta, FangYuan33, GN-Yu, IsChristina, xBLACKICEx, guowei-gong, Cathay-Chen, mgisr, JoseHung, qualifier1024, pengchzn, Guanngxu, longsizhuo, L-Super, what-is-me, yuan0221, lhxsm, Slone123c, WSL0809, longranger2, theNefelibatas, xiongsp, JeffersonHuang, hongyun-robot, K3v123, yuelinxin, a16su, gaofer, malone6, Wonderdch, xjr7670, DullSword, Horbin-Magician, NI-SW, reeswell, XC-Zero, XiaChuerwu, yd-j, iron-irax, huawuque404, MolDuM, Nigh, KorsChen, foursevenlove, 52coder, bubble9um, youshaoXG, curly210102, gltianwen, fanchenggang, Transmigration-zhou, FloranceYeh, FreddieLi, ShiMaRing, lipusheng, Javesun99, JackYang-hellobobo, shanghai-Jerry, 0130w, Keynman, psychelzh, logan-qiu, ZnYang2018, MwumLi, 1ch0, Phoenix0415, qingpeng9802, Richard-Zhang1019, QiLOL, Suremotoo, Turing-1024-Lee, Evilrabbit520, GaochaoZhu, ZJKung, linzeyan, hezhizhen, ZongYangL, beintentional, czruby, coderlef, dshlstarr, szu17dmy, fbigm, gledfish, hts0000, boloboloda, iStig, jiaxianhua, wenjianmin, keshida, kilikilikid, lclc6, lwbaptx, liuxjerry, lucaswangdev, lyl625760, chadyi, noobcodemaker, selear, siqyka, syd168, 4yDX3906, tao363, wangwang105, weibk, yabo083, yi427, yishangzhang, zhouLion, baagod, ElaBosak233, xb534, luluxia, yanedie, thomasq0, YangXuanyi and th1nk3r-ing.
|
This book is continuously improved with the joint efforts of many contributors from the open-source community. Thanks to each writer who invested their time and energy, listed in the order generated by GitHub: krahets, coderonion, Gonglja, nuomi1, Reanon, justin-tse, hpstory, danielsss, curtishd, night-cruise, S-N-O-R-L-A-X, msk397, gvenusleo, khoaxuantu, RiverTwilight, rongyi, gyt95, zhuoqinyue, K3v123, Zuoxun, mingXta, hello-ikun, FangYuan33, GN-Yu, yuelinxin, longsizhuo, Cathay-Chen, guowei-gong, xBLACKICEx, IsChristina, JoseHung, qualifier1024, QiLOL, pengchzn, Guanngxu, L-Super, WSL0809, Slone123c, lhxsm, yuan0221, what-is-me, theNefelibatas, longranger2, cy-by-side, xiongsp, JeffersonHuang, Transmigration-zhou, magentaqin, Wonderdch, malone6, xiaomiusa87, gaofer, bluebean-cloud, a16su, Shyam-Chen, nanlei, hongyun-robot, Phoenix0415, MolDuM, Nigh, he-weilai, junminhong, mgisr, iron-irax, yd-j, XiaChuerwu, XC-Zero, seven1240, SamJin98, wodray, reeswell, NI-SW, Horbin-Magician, Enlightenus, xjr7670, YangXuanyi, DullSword, boloboloda, iStig, qq909244296, jiaxianhua, wenjianmin, keshida, kilikilikid, lclc6, lwbaptx, liuxjerry, lucaswangdev, lyl625760, hts0000, gledfish, fbigm, echo1937, szu17dmy, dshlstarr, Yucao-cy, coderlef, czruby, bongbongbakudan, beintentional, ZongYangL, ZhongYuuu, luluxia, xb534, bitsmi, ElaBosak233, baagod, zhouLion, yishangzhang, yi427, yabo083, weibk, wangwang105, th1nk3r-ing, tao363, 4yDX3906, syd168, steventimes, sslmj2020, smilelsb, siqyka, selear, sdshaoda, Xi-Row, popozhu, nuquist19, noobcodemaker, XiaoK29, chadyi, ZhongGuanbin, shanghai-Jerry, JackYang-hellobobo, Javesun99, lipusheng, BlindTerran, ShiMaRing, FreddieLi, FloranceYeh, iFleey, fanchenggang, gltianwen, goerll, Dr-XYZ, nedchu, curly210102, CuB3y0nd, KraHsu, CarrotDLaw, youshaoXG, bubble9um, fanenr, eagleanurag, LifeGoesOnionOnionOnion, 52coder, foursevenlove, KorsChen, hezhizhen, linzeyan, ZJKung, GaochaoZhu, hopkings2008, yang-le, Evilrabbit520, Turing-1024-Lee, thomasq0, Suremotoo, Allen-Scai, Risuntsy, Richard-Zhang1019, qingpeng9802, primexiao, nidhoggfgg, 1ch0, MwumLi, martinx, ZnYang2018, hugtyftg, logan-qiu, psychelzh, Keynman, KeiichiKasai and 0130w.
|
||||||
|
|
||||||
The code review work for this book was completed by codingonion, Gonglja, gvenusleo, hpstory, justin‐tse, khoaxuantu, krahets, night-cruise, nuomi1, and Reanon (listed in alphabetical order). Thanks to them for their time and effort, ensuring the standardization and uniformity of the code in various languages.
|
The code review work for this book was completed by coderonion, Gonglja, gvenusleo, hpstory, justin‐tse, khoaxuantu, krahets, night-cruise, nuomi1, Reanon and rongyi (listed in alphabetical order). Thanks to them for their time and effort, ensuring the standardization and uniformity of the code in various languages.
|
||||||
|
|
||||||
Throughout the creation of this book, numerous individuals provided invaluable assistance, including but not limited to:
|
Throughout the creation of this book, numerous individuals provided invaluable assistance, including but not limited to:
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
# Binary search
|
# Binary search
|
||||||
|
|
||||||
<u>Binary search</u> is an efficient search algorithm based on the divide-and-conquer strategy. It utilizes the orderliness of data, reducing the search range by half each round until the target element is found or the search interval is empty.
|
<u>Binary search</u> is an efficient search algorithm that uses a divide-and-conquer strategy. It takes advantage of the sorted order of elements in an array by reducing the search interval by half in each iteration, continuing until either the target element is found or the search interval becomes empty.
|
||||||
|
|
||||||
!!! question
|
!!! question
|
||||||
|
|
||||||
Given an array `nums` of length $n$, with elements arranged in ascending order and non-repeating. Please find and return the index of element `target` in this array. If the array does not contain the element, return $-1$. An example is shown in the figure below.
|
Given an array `nums` of length $n$, where elements are arranged in ascending order without duplicates. Please find and return the index of element `target` in this array. If the array does not contain the element, return $-1$. An example is shown in the figure below.
|
||||||
|
|
||||||
![Binary search example data](binary_search.assets/binary_search_example.png)
|
![Binary search example data](binary_search.assets/binary_search_example.png)
|
||||||
|
|
||||||
As shown in the figure below, we first initialize pointers $i = 0$ and $j = n - 1$, pointing to the first and last elements of the array, representing the search interval $[0, n - 1]$. Please note that square brackets indicate a closed interval, which includes the boundary values themselves.
|
As shown in the figure below, we firstly initialize pointers with $i = 0$ and $j = n - 1$, pointing to the first and last element of the array respectively. They also represent the whole search interval $[0, n - 1]$. Please note that square brackets indicate a closed interval, which includes the boundary values themselves.
|
||||||
|
|
||||||
Next, perform the following two steps in a loop.
|
And then the following two steps may be performed in a loop.
|
||||||
|
|
||||||
1. Calculate the midpoint index $m = \lfloor {(i + j) / 2} \rfloor$, where $\lfloor \: \rfloor$ denotes the floor operation.
|
1. Calculate the midpoint index $m = \lfloor {(i + j) / 2} \rfloor$, where $\lfloor \: \rfloor$ denotes the floor operation.
|
||||||
2. Compare the size of `nums[m]` and `target`, divided into the following three scenarios.
|
2. Based on the comparison between the value of `nums[m]` and `target`, one of the following three cases will be chosen to execute.
|
||||||
1. If `nums[m] < target`, it indicates that `target` is in the interval $[m + 1, j]$, thus set $i = m + 1$.
|
1. If `nums[m] < target`, it indicates that `target` is in the interval $[m + 1, j]$, thus set $i = m + 1$.
|
||||||
2. If `nums[m] > target`, it indicates that `target` is in the interval $[i, m - 1]$, thus set $j = m - 1$.
|
2. If `nums[m] > target`, it indicates that `target` is in the interval $[i, m - 1]$, thus set $j = m - 1$.
|
||||||
3. If `nums[m] = target`, it indicates that `target` is found, thus return index $m$.
|
3. If `nums[m] = target`, it indicates that `target` is found, thus return index $m$.
|
||||||
|
|
||||||
If the array does not contain the target element, the search interval will eventually reduce to empty. In this case, return $-1$.
|
If the array does not contain the target element, the search interval will eventually reduce to empty, ending up returning $-1$.
|
||||||
|
|
||||||
=== "<1>"
|
=== "<1>"
|
||||||
![Binary search process](binary_search.assets/binary_search_step1.png)
|
![Binary search process](binary_search.assets/binary_search_step1.png)
|
||||||
|
@ -41,7 +41,7 @@ If the array does not contain the target element, the search interval will event
|
||||||
=== "<7>"
|
=== "<7>"
|
||||||
![binary_search_step7](binary_search.assets/binary_search_step7.png)
|
![binary_search_step7](binary_search.assets/binary_search_step7.png)
|
||||||
|
|
||||||
It's worth noting that since $i$ and $j$ are both of type `int`, **$i + j$ might exceed the range of `int` type**. To avoid large number overflow, we usually use the formula $m = \lfloor {i + (j - i) / 2} \rfloor$ to calculate the midpoint.
|
It's worth noting that as $i$ and $j$ are both of type `int`, **$i + j$ might exceed the range of `int` type**. To avoid large number overflow, we usually use the formula $m = \lfloor {i + (j - i) / 2} \rfloor$ to calculate the midpoint.
|
||||||
|
|
||||||
The code is as follows:
|
The code is as follows:
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@ The code is as follows:
|
||||||
[file]{binary_search}-[class]{}-[func]{binary_search}
|
[file]{binary_search}-[class]{}-[func]{binary_search}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Time complexity is $O(\log n)$** : In the binary loop, the interval reduces by half each round, hence the number of iterations is $\log_2 n$.
|
**Time complexity is $O(\log n)$** : In the binary loop, the interval decreases by half each round, hence the number of iterations is $\log_2 n$.
|
||||||
|
|
||||||
**Space complexity is $O(1)$** : Pointers $i$ and $j$ use constant size space.
|
**Space complexity is $O(1)$** : Pointers $i$ and $j$ occupies constant size of space.
|
||||||
|
|
||||||
## Interval representation methods
|
## Interval representation methods
|
||||||
|
|
||||||
Besides the aforementioned closed interval, a common interval representation is the "left-closed right-open" interval, defined as $[0, n)$, where the left boundary includes itself, and the right boundary does not include itself. In this representation, the interval $[i, j)$ is empty when $i = j$.
|
Besides the above closed interval, another common interval representation is the "left-closed right-open" interval, defined as $[0, n)$, where the left boundary includes itself, and the right boundary does not. In this representation, the interval $[i, j)$ is empty when $i = j$.
|
||||||
|
|
||||||
We can implement a binary search algorithm with the same functionality based on this representation:
|
We can implement a binary search algorithm with the same functionality based on this representation:
|
||||||
|
|
||||||
|
@ -63,9 +63,9 @@ We can implement a binary search algorithm with the same functionality based on
|
||||||
[file]{binary_search}-[class]{}-[func]{binary_search_lcro}
|
[file]{binary_search}-[class]{}-[func]{binary_search_lcro}
|
||||||
```
|
```
|
||||||
|
|
||||||
As shown in the figure below, in the two types of interval representations, the initialization of the binary search algorithm, the loop condition, and the narrowing interval operation are different.
|
As shown in the figure below, under the two types of interval representations, the initialization, loop condition, and narrowing interval operation of the binary search algorithm differ.
|
||||||
|
|
||||||
Since both boundaries in the "closed interval" representation are defined as closed, the operations to narrow the interval through pointers $i$ and $j$ are also symmetrical. This makes it less prone to errors, **therefore, it is generally recommended to use the "closed interval" approach**.
|
Since both boundaries in the "closed interval" representation are inclusive, the operations to narrow the interval through pointers $i$ and $j$ are also symmetrical. This makes it less prone to errors, **therefore, it is generally recommended to use the "closed interval" approach**.
|
||||||
|
|
||||||
![Two types of interval definitions](binary_search.assets/binary_search_ranges.png)
|
![Two types of interval definitions](binary_search.assets/binary_search_ranges.png)
|
||||||
|
|
||||||
|
@ -73,11 +73,11 @@ Since both boundaries in the "closed interval" representation are defined as clo
|
||||||
|
|
||||||
Binary search performs well in both time and space aspects.
|
Binary search performs well in both time and space aspects.
|
||||||
|
|
||||||
- Binary search is time-efficient. With large data volumes, the logarithmic time complexity has a significant advantage. For instance, when the data size $n = 2^{20}$, linear search requires $2^{20} = 1048576$ iterations, while binary search only requires $\log_2 2^{20} = 20$ iterations.
|
- Binary search is time-efficient. With large dataset, the logarithmic time complexity offers a major advantage. For instance, given a dataset with size $n = 2^{20}$, linear search requires $2^{20} = 1048576$ iterations, while binary search only demands $\log_2 2^{20} = 20$ loops.
|
||||||
- Binary search does not require extra space. Compared to search algorithms that rely on additional space (like hash search), binary search is more space-efficient.
|
- Binary search does not need extra space. Compared to search algorithms that rely on additional space (like hash search), binary search is more space-efficient.
|
||||||
|
|
||||||
However, binary search is not suitable for all situations, mainly for the following reasons.
|
However, binary search may not be suitable for all scenarios due to the following concerns.
|
||||||
|
|
||||||
- Binary search is only applicable to ordered data. If the input data is unordered, it is not worth sorting it just to use binary search, as sorting algorithms typically have a time complexity of $O(n \log n)$, which is higher than both linear and binary search. For scenarios with frequent element insertion to maintain array order, inserting elements into specific positions has a time complexity of $O(n)$, which is also quite costly.
|
- Binary search can only be applied to sorted data. Unsorted data must be sorted before applying binary search, which may not be worthwhile as sorting algorithm typically has a time complexity of $O(n \log n)$. Such cost is even higher than linear search, not to mention binary search itself. For scenarios with frequent insertion, the cost of remaining the array in order is pretty high as the time complexity of inserting new elements into specific positions is $O(n)$.
|
||||||
- Binary search is only applicable to arrays. Binary search requires non-continuous (jumping) element access, which is inefficient in linked lists, thus not suitable for use in linked lists or data structures based on linked lists.
|
- Binary search may use array only. Binary search requires non-continuous (jumping) element access, which is inefficient in linked list. As a result, linked list or data structures based on linked list may not be suitable for this algorithm.
|
||||||
- With small data volumes, linear search performs better. In linear search, each round only requires 1 decision operation; whereas in binary search, it involves 1 addition, 1 division, 1 to 3 decision operations, 1 addition (subtraction), totaling 4 to 6 operations; therefore, when data volume $n$ is small, linear search can be faster than binary search.
|
- Linear search performs better on small dataset. In linear search, only 1 decision operation is required for each iteration; whereas in binary search, it involves 1 addition, 1 division, 1 to 3 decision operations, 1 addition (subtraction), totaling 4 to 6 operations. Therefore, if data size $n$ is small, linear search is faster than binary search.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Hash optimization strategies
|
# Hash optimization strategies
|
||||||
|
|
||||||
In algorithm problems, **we often reduce the time complexity of algorithms by replacing linear search with hash search**. Let's use an algorithm problem to deepen understanding.
|
In algorithm problems, **we often reduce the time complexity of an algorithm by replacing a linear search with a hash-based search**. Let's use an algorithm problem to deepen the understanding.
|
||||||
|
|
||||||
!!! question
|
!!! question
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ In algorithm problems, **we often reduce the time complexity of algorithms by re
|
||||||
|
|
||||||
## Linear search: trading time for space
|
## Linear search: trading time for space
|
||||||
|
|
||||||
Consider traversing all possible combinations directly. As shown in the figure below, we initiate a two-layer loop, and in each round, we determine whether the sum of the two integers equals `target`. If so, we return their indices.
|
Consider traversing through all possible combinations directly. As shown in the figure below, we initiate a nested loop, and in each iteration, we determine whether the sum of the two integers equals `target`. If so, we return their indices.
|
||||||
|
|
||||||
![Linear search solution for two-sum problem](replace_linear_by_hashing.assets/two_sum_brute_force.png)
|
![Linear search solution for two-sum problem](replace_linear_by_hashing.assets/two_sum_brute_force.png)
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@ The code is shown below:
|
||||||
[file]{two_sum}-[class]{}-[func]{two_sum_brute_force}
|
[file]{two_sum}-[class]{}-[func]{two_sum_brute_force}
|
||||||
```
|
```
|
||||||
|
|
||||||
This method has a time complexity of $O(n^2)$ and a space complexity of $O(1)$, which is very time-consuming with large data volumes.
|
This method has a time complexity of $O(n^2)$ and a space complexity of $O(1)$, which can be very time-consuming with large data volumes.
|
||||||
|
|
||||||
## Hash search: trading space for time
|
## Hash search: trading space for time
|
||||||
|
|
||||||
Consider using a hash table, with key-value pairs being the array elements and their indices, respectively. Loop through the array, performing the steps shown in the figure below each round.
|
Consider using a hash table, where the key-value pairs are the array elements and their indices, respectively. Loop through the array, performing the steps shown in the figure below during each iteration.
|
||||||
|
|
||||||
1. Check if the number `target - nums[i]` is in the hash table. If so, directly return the indices of these two elements.
|
1. Check if the number `target - nums[i]` is in the hash table. If so, directly return the indices of these two elements.
|
||||||
2. Add the key-value pair `nums[i]` and index `i` to the hash table.
|
2. Add the key-value pair `nums[i]` and index `i` to the hash table.
|
||||||
|
@ -42,6 +42,6 @@ The implementation code is shown below, requiring only a single loop:
|
||||||
[file]{two_sum}-[class]{}-[func]{two_sum_hash_table}
|
[file]{two_sum}-[class]{}-[func]{two_sum_hash_table}
|
||||||
```
|
```
|
||||||
|
|
||||||
This method reduces the time complexity from $O(n^2)$ to $O(n)$ by using hash search, greatly improving the running efficiency.
|
This method reduces the time complexity from $O(n^2)$ to $O(n)$ by using hash search, significantly enhancing runtime efficiency.
|
||||||
|
|
||||||
As it requires maintaining an additional hash table, the space complexity is $O(n)$. **Nevertheless, this method has a more balanced time-space efficiency overall, making it the optimal solution for this problem**.
|
As it requires maintaining an additional hash table, the space complexity is $O(n)$. **Nevertheless, this method has a more balanced time-space efficiency overall, making it the optimal solution for this problem**.
|
||||||
|
|
|
@ -258,9 +258,9 @@
|
||||||
<h3>Code reviewers</h3>
|
<h3>Code reviewers</h3>
|
||||||
<div class="profile-div">
|
<div class="profile-div">
|
||||||
<div class="profile-cell">
|
<div class="profile-cell">
|
||||||
<a href="https://github.com/codingonion">
|
<a href="https://github.com/coderonion">
|
||||||
<img class="profile-img" src="../assets/avatar/avatar_codingonion.jpg" alt="Reviewer: codingonion" />
|
<img class="profile-img" src="../assets/avatar/avatar_coderonion.jpg" alt="Reviewer: coderonion" />
|
||||||
<br><b>codingonion</b>
|
<br><b>coderonion</b>
|
||||||
<br><sub>Zig, Rust</sub>
|
<br><sub>Zig, Rust</sub>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -414,7 +414,7 @@
|
||||||
<!-- contributors -->
|
<!-- contributors -->
|
||||||
<div style="margin: 2em auto;">
|
<div style="margin: 2em auto;">
|
||||||
<h3>Contributors</h3>
|
<h3>Contributors</h3>
|
||||||
<p>This book has been optimized by the efforts of over 180 contributors. We sincerely thank them for their invaluable time and contributions!</p>
|
<p>This book has been refined by the efforts of over 180 contributors. We sincerely thank them for their invaluable time and contributions!</p>
|
||||||
<a href="https://github.com/krahets/hello-algo/graphs/contributors">
|
<a href="https://github.com/krahets/hello-algo/graphs/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=krahets/hello-algo&max=300&columns=16" alt="Contributors" style="width: 100%; max-width: 38.5em;">
|
<img src="https://contrib.rocks/image?repo=krahets/hello-algo&max=300&columns=16" alt="Contributors" style="width: 100%; max-width: 38.5em;">
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -9,7 +9,7 @@ site_dir: site
|
||||||
repo_name: krahets/hello-algo
|
repo_name: krahets/hello-algo
|
||||||
repo_url: https://github.com/krahets/hello-algo
|
repo_url: https://github.com/krahets/hello-algo
|
||||||
edit_uri: tree/main/docs
|
edit_uri: tree/main/docs
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
|
|
||||||
# Copyright
|
# Copyright
|
||||||
copyright: Copyright © 2024 krahets<br>The website content is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a>
|
copyright: Copyright © 2024 krahets<br>The website content is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a>
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://www.hello-algo.com/zh-hant/">
|
<a href="https://www.hello-algo.com/zh-hant/">
|
||||||
<img src="https://www.hello-algo.com/zh-hant/index.assets/btn_read_online_dark.svg" width="145"></a>
|
<img src="https://www.hello-algo.com/zh-hant/index.assets/btn_read_online_dark.svg" width="145"></a>
|
||||||
|
<a href="https://github.com/krahets/hello-algo/releases">
|
||||||
|
<img src="https://www.hello-algo.com/zh-hant/index.assets/btn_download_pdf_dark.svg" width="145"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|
|
@ -111,16 +111,29 @@ int popLast(ArrayDeque *deque) {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 返回陣列用於列印 */
|
||||||
|
int *toArray(ArrayDeque *deque, int *queSize) {
|
||||||
|
*queSize = deque->queSize;
|
||||||
|
int *res = (int *)calloc(deque->queSize, sizeof(int));
|
||||||
|
int j = deque->front;
|
||||||
|
for (int i = 0; i < deque->queSize; i++) {
|
||||||
|
res[i] = deque->nums[j % deque->queCapacity];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
int main() {
|
int main() {
|
||||||
/* 初始化佇列 */
|
/* 初始化佇列 */
|
||||||
int capacity = 10;
|
int capacity = 10;
|
||||||
|
int queSize;
|
||||||
ArrayDeque *deque = newArrayDeque(capacity);
|
ArrayDeque *deque = newArrayDeque(capacity);
|
||||||
pushLast(deque, 3);
|
pushLast(deque, 3);
|
||||||
pushLast(deque, 2);
|
pushLast(deque, 2);
|
||||||
pushLast(deque, 5);
|
pushLast(deque, 5);
|
||||||
printf("雙向佇列 deque = ");
|
printf("雙向佇列 deque = ");
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
|
|
||||||
/* 訪問元素 */
|
/* 訪問元素 */
|
||||||
int peekFirstNum = peekFirst(deque);
|
int peekFirstNum = peekFirst(deque);
|
||||||
|
@ -131,18 +144,18 @@ int main() {
|
||||||
/* 元素入列 */
|
/* 元素入列 */
|
||||||
pushLast(deque, 4);
|
pushLast(deque, 4);
|
||||||
printf("元素 4 佇列尾入列後 deque = ");
|
printf("元素 4 佇列尾入列後 deque = ");
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
pushFirst(deque, 1);
|
pushFirst(deque, 1);
|
||||||
printf("元素 1 佇列首入列後 deque = ");
|
printf("元素 1 佇列首入列後 deque = ");
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
|
|
||||||
/* 元素出列 */
|
/* 元素出列 */
|
||||||
int popLastNum = popLast(deque);
|
int popLastNum = popLast(deque);
|
||||||
printf("佇列尾出列元素 = %d ,佇列尾出列後 deque= ", popLastNum);
|
printf("佇列尾出列元素 = %d ,佇列尾出列後 deque= ", popLastNum);
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
int popFirstNum = popFirst(deque);
|
int popFirstNum = popFirst(deque);
|
||||||
printf("佇列首出列元素 = %d ,佇列首出列後 deque= ", popFirstNum);
|
printf("佇列首出列元素 = %d ,佇列首出列後 deque= ", popFirstNum);
|
||||||
printArray(deque->nums, deque->queSize);
|
printArray(toArray(deque, &queSize), queSize);
|
||||||
|
|
||||||
/* 獲取佇列的長度 */
|
/* 獲取佇列的長度 */
|
||||||
int dequeSize = size(deque);
|
int dequeSize = size(deque);
|
||||||
|
@ -156,4 +169,4 @@ int main() {
|
||||||
delArrayDeque(deque);
|
delArrayDeque(deque);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -74,10 +74,23 @@ int pop(ArrayQueue *queue) {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 返回陣列用於列印 */
|
||||||
|
int *toArray(ArrayQueue *queue, int *queSize) {
|
||||||
|
*queSize = queue->queSize;
|
||||||
|
int *res = (int *)calloc(queue->queSize, sizeof(int));
|
||||||
|
int j = queue->front;
|
||||||
|
for (int i = 0; i < queue->queSize; i++) {
|
||||||
|
res[i] = queue->nums[j % queue->queCapacity];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
int main() {
|
int main() {
|
||||||
/* 初始化佇列 */
|
/* 初始化佇列 */
|
||||||
int capacity = 10;
|
int capacity = 10;
|
||||||
|
int queSize;
|
||||||
ArrayQueue *queue = newArrayQueue(capacity);
|
ArrayQueue *queue = newArrayQueue(capacity);
|
||||||
|
|
||||||
/* 元素入列 */
|
/* 元素入列 */
|
||||||
|
@ -87,7 +100,7 @@ int main() {
|
||||||
push(queue, 5);
|
push(queue, 5);
|
||||||
push(queue, 4);
|
push(queue, 4);
|
||||||
printf("佇列 queue = ");
|
printf("佇列 queue = ");
|
||||||
printArray(queue->nums, queue->queSize);
|
printArray(toArray(queue, &queSize), queSize);
|
||||||
|
|
||||||
/* 訪問佇列首元素 */
|
/* 訪問佇列首元素 */
|
||||||
int peekNum = peek(queue);
|
int peekNum = peek(queue);
|
||||||
|
@ -96,7 +109,7 @@ int main() {
|
||||||
/* 元素出列 */
|
/* 元素出列 */
|
||||||
peekNum = pop(queue);
|
peekNum = pop(queue);
|
||||||
printf("出列元素 pop = %d ,出列後 queue = ", peekNum);
|
printf("出列元素 pop = %d ,出列後 queue = ", peekNum);
|
||||||
printArray(queue->nums, queue->queSize);
|
printArray(toArray(queue, &queSize), queSize);
|
||||||
|
|
||||||
/* 獲取佇列的長度 */
|
/* 獲取佇列的長度 */
|
||||||
int queueSize = size(queue);
|
int queueSize = size(queue);
|
||||||
|
@ -111,11 +124,11 @@ int main() {
|
||||||
push(queue, i);
|
push(queue, i);
|
||||||
pop(queue);
|
pop(queue);
|
||||||
printf("第 %d 輪入列 + 出列後 queue = ", i);
|
printf("第 %d 輪入列 + 出列後 queue = ", i);
|
||||||
printArray(queue->nums, queue->queSize);
|
printArray(toArray(queue, &queSize), queSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 釋放記憶體
|
// 釋放記憶體
|
||||||
delArrayQueue(queue);
|
delArrayQueue(queue);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -115,9 +115,9 @@ int main() {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
int l = abt.left(i), r = abt.right(i), p = abt.parent(i);
|
int l = abt.left(i), r = abt.right(i), p = abt.parent(i);
|
||||||
cout << "\n當前節點的索引為 " << i << ",值為 " << abt.val(i) << "\n";
|
cout << "\n當前節點的索引為 " << i << ",值為 " << abt.val(i) << "\n";
|
||||||
cout << "其左子節點的索引為 " << l << ",值為 " << (l != INT_MAX ? to_string(abt.val(l)) : "nullptr") << "\n";
|
cout << "其左子節點的索引為 " << l << ",值為 " << (abt.val(l) != INT_MAX ? to_string(abt.val(l)) : "nullptr") << "\n";
|
||||||
cout << "其右子節點的索引為 " << r << ",值為 " << (r != INT_MAX ? to_string(abt.val(r)) : "nullptr") << "\n";
|
cout << "其右子節點的索引為 " << r << ",值為 " << (abt.val(r) != INT_MAX ? to_string(abt.val(r)) : "nullptr") << "\n";
|
||||||
cout << "其父節點的索引為 " << p << ",值為 " << (p != INT_MAX ? to_string(abt.val(p)) : "nullptr") << "\n";
|
cout << "其父節點的索引為 " << p << ",值為 " << (abt.val(p) != INT_MAX ? to_string(abt.val(p)) : "nullptr") << "\n";
|
||||||
|
|
||||||
// 走訪樹
|
// 走訪樹
|
||||||
vector<int> res = abt.levelOrder();
|
vector<int> res = abt.levelOrder();
|
||||||
|
|
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 465 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 477 KiB After Width: | Height: | Size: 122 KiB |
|
@ -50,6 +50,7 @@
|
||||||
| front of the queue | 队首 | 佇列首 |
|
| front of the queue | 队首 | 佇列首 |
|
||||||
| rear of the queue | 队尾 | 佇列尾 |
|
| rear of the queue | 队尾 | 佇列尾 |
|
||||||
| hash table | 哈希表 | 雜湊表 |
|
| hash table | 哈希表 | 雜湊表 |
|
||||||
|
| hash set | 哈希集合 | 雜湊集合 |
|
||||||
| bucket | 桶 | 桶 |
|
| bucket | 桶 | 桶 |
|
||||||
| hash function | 哈希函数 | 雜湊函式 |
|
| hash function | 哈希函数 | 雜湊函式 |
|
||||||
| hash collision | 哈希冲突 | 雜湊衝突 |
|
| hash collision | 哈希冲突 | 雜湊衝突 |
|
||||||
|
|
|
@ -71,6 +71,16 @@
|
||||||
|
|
||||||
另一方面,必要使用鏈結串列的情況主要是二元樹和圖。堆疊和佇列往往會使用程式語言提供的 `stack` 和 `queue` ,而非鏈結串列。
|
另一方面,必要使用鏈結串列的情況主要是二元樹和圖。堆疊和佇列往往會使用程式語言提供的 `stack` 和 `queue` ,而非鏈結串列。
|
||||||
|
|
||||||
**Q**:初始化串列 `res = [0] * self.size()` 操作,會導致 `res` 的每個元素引用相同的位址嗎?
|
**Q**:操作 `res = [[0]] * n` 生成了一個二維串列,其中每一個 `[0]` 都是獨立的嗎?
|
||||||
|
|
||||||
不會。但二維陣列會有這個問題,例如初始化二維串列 `res = [[0]] * self.size()` ,則多次引用了同一個串列 `[0]` 。
|
不是獨立的。此二維串列中,所有的 `[0]` 實際上是同一個物件的引用。如果我們修改其中一個元素,會發現所有的對應元素都會隨之改變。
|
||||||
|
|
||||||
|
如果希望二維串列中的每個 `[0]` 都是獨立的,可以使用 `res = [[0] for _ in range(n)]` 來實現。這種方式的原理是初始化了 $n$ 個獨立的 `[0]` 串列物件。
|
||||||
|
|
||||||
|
**Q**:操作 `res = [0] * n` 生成了一個串列,其中每一個整數 0 都是獨立的嗎?
|
||||||
|
|
||||||
|
在該串列中,所有整數 0 都是同一個物件的引用。這是因為 Python 對小整數(通常是 -5 到 256)採用了快取池機制,以便最大化物件複用,從而提升效能。
|
||||||
|
|
||||||
|
雖然它們指向同一個物件,但我們仍然可以獨立修改串列中的每個元素,這是因為 Python 的整數是“不可變物件”。當我們修改某個元素時,實際上是切換為另一個物件的引用,而不是改變原有物件本身。
|
||||||
|
|
||||||
|
然而,當串列元素是“可變物件”時(例如串列、字典或類別例項等),修改某個元素會直接改變該物件本身,所有引用該物件的元素都會產生相同變化。
|
||||||
|
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 13 KiB |
|
@ -1120,7 +1120,7 @@ $$
|
||||||
|
|
||||||
生物學的“細胞分裂”是指數階增長的典型例子:初始狀態為 $1$ 個細胞,分裂一輪後變為 $2$ 個,分裂兩輪後變為 $4$ 個,以此類推,分裂 $n$ 輪後有 $2^n$ 個細胞。
|
生物學的“細胞分裂”是指數階增長的典型例子:初始狀態為 $1$ 個細胞,分裂一輪後變為 $2$ 個,分裂兩輪後變為 $4$ 個,以此類推,分裂 $n$ 輪後有 $2^n$ 個細胞。
|
||||||
|
|
||||||
下圖和以下程式碼模擬了細胞分裂的過程,時間複雜度為 $O(2^n)$ :
|
下圖和以下程式碼模擬了細胞分裂的過程,時間複雜度為 $O(2^n)$ 。請注意,輸入 $n$ 表示分裂輪數,返回值 `count` 表示總分裂次數。
|
||||||
|
|
||||||
```src
|
```src
|
||||||
[file]{time_complexity}-[class]{}-[func]{exponential}
|
[file]{time_complexity}-[class]{}-[func]{exponential}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
- 整理撲克的過程與插入排序演算法非常類似。插入排序演算法適合排序小型資料集。
|
- 整理撲克的過程與插入排序演算法非常類似。插入排序演算法適合排序小型資料集。
|
||||||
- 貨幣找零的步驟本質上是貪婪演算法,每一步都採取當前看來最好的選擇。
|
- 貨幣找零的步驟本質上是貪婪演算法,每一步都採取當前看來最好的選擇。
|
||||||
- 演算法是在有限時間內解決特定問題的一組指令或操作步驟,而資料結構是計算機中組織和儲存資料的方式。
|
- 演算法是在有限時間內解決特定問題的一組指令或操作步驟,而資料結構是計算機中組織和儲存資料的方式。
|
||||||
- 資料結構與演算法緊密相連。資料結構是演算法的基石,而演算法是資料結構發揮作用的舞臺。
|
- 資料結構與演算法緊密相連。資料結構是演算法的基石,而演算法為資料結構注入生命力。
|
||||||
- 我們可以將資料結構與演算法類比為拼裝積木,積木代表資料,積木的形狀和連線方式等代表資料結構,拼裝積木的步驟則對應演算法。
|
- 我們可以將資料結構與演算法類比為拼裝積木,積木代表資料,積木的形狀和連線方式等代表資料結構,拼裝積木的步驟則對應演算法。
|
||||||
|
|
||||||
### Q & A
|
### Q & A
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
如下圖所示,資料結構與演算法高度相關、緊密結合,具體表現在以下三個方面。
|
如下圖所示,資料結構與演算法高度相關、緊密結合,具體表現在以下三個方面。
|
||||||
|
|
||||||
- 資料結構是演算法的基石。資料結構為演算法提供了結構化儲存的資料,以及操作資料的方法。
|
- 資料結構是演算法的基石。資料結構為演算法提供了結構化儲存的資料,以及操作資料的方法。
|
||||||
- 演算法是資料結構發揮作用的舞臺。資料結構本身僅儲存資料資訊,結合演算法才能解決特定問題。
|
- 演算法為資料結構注入生命力。資料結構本身僅儲存資料資訊,結合演算法才能解決特定問題。
|
||||||
- 演算法通常可以基於不同的資料結構實現,但執行效率可能相差很大,選擇合適的資料結構是關鍵。
|
- 演算法通常可以基於不同的資料結構實現,但執行效率可能相差很大,選擇合適的資料結構是關鍵。
|
||||||
|
|
||||||
![資料結構與演算法的關係](what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png)
|
![資料結構與演算法的關係](what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png)
|
||||||
|
|
|
@ -30,9 +30,9 @@
|
||||||
|
|
||||||
## 致謝
|
## 致謝
|
||||||
|
|
||||||
本書在開源社群眾多貢獻者的共同努力下不斷完善。感謝每一位投入時間與精力的撰稿人,他們是(按照 GitHub 自動生成的順序):krahets、Gonglja、nuomi1、codingonion、Reanon、justin-tse、hpstory、danielsss、curtishd、night-cruise、S-N-O-R-L-A-X、msk397、gvenusleo、RiverTwilight、gyt95、zhuoqinyue、Zuoxun、mingXta、hello-ikun、khoaxuantu、FangYuan33、GN-Yu、longsizhuo、mgisr、Cathay-Chen、guowei-gong、xBLACKICEx、K3v123、IsChristina、JoseHung、qualifier1024、pengchzn、Guanngxu、QiLOL、L-Super、WSL0809、Slone123c、lhxsm、yuan0221、what-is-me、rongyi、JeffersonHuang、longranger2、theNefelibatas、yuelinxin、xiongsp、nanlei、a16su、cy-by-side、gaofer、malone6、Wonderdch、hongyun-robot、XiaChuerwu、yd-j、bluebean-cloud、iron-irax、he-weilai、Nigh、MolDuM、Phoenix0415、XC-Zero、SamJin98、reeswell、NI-SW、Horbin-Magician、xjr7670、YangXuanyi、DullSword、iStig、qq909244296、jiaxianhua、wenjianmin、keshida、kilikilikid、lclc6、lwbaptx、luluxia、boloboloda、hts0000、gledfish、fbigm、echo1937、szu17dmy、dshlstarr、coderlef、czruby、beintentional、KeiichiKasai、xb534、ElaBosak233、baagod、zhouLion、yishangzhang、yi427、yabo083、weibk、wangwang105、th1nk3r-ing、tao363、4yDX3906、syd168、siqyka、selear、sdshaoda、noobcodemaker、chadyi、lyl625760、lucaswangdev、liuxjerry、0130w、shanghai-Jerry、JackYang-hellobobo、Javesun99、lipusheng、ShiMaRing、FreddieLi、FloranceYeh、Transmigration-zhou、fanchenggang、gltianwen、Dr-XYZ、curly210102、CuB3y0nd、youshaoXG、bubble9um、fanenr、52coder、foursevenlove、KorsChen、ZongYangL、hezhizhen、linzeyan、ZJKung、GaochaoZhu、yang-le、Evilrabbit520、Turing-1024-Lee、Suremotoo、Allen-Scai、Richard-Zhang1019、qingpeng9802、primexiao、nidhoggfgg、1ch0、MwumLi、ZnYang2018、hugtyftg、logan-qiu、psychelzh 和 Keynman 。
|
本書在開源社群眾多貢獻者的共同努力下不斷完善。感謝每一位投入時間與精力的撰稿人,他們是(按照 GitHub 自動生成的順序):krahets、coderonion、Gonglja、nuomi1、Reanon、justin-tse、hpstory、danielsss、curtishd、night-cruise、S-N-O-R-L-A-X、msk397、gvenusleo、khoaxuantu、RiverTwilight、rongyi、gyt95、zhuoqinyue、K3v123、Zuoxun、mingXta、hello-ikun、FangYuan33、GN-Yu、yuelinxin、longsizhuo、Cathay-Chen、guowei-gong、xBLACKICEx、IsChristina、JoseHung、qualifier1024、QiLOL、pengchzn、Guanngxu、L-Super、WSL0809、Slone123c、lhxsm、yuan0221、what-is-me、theNefelibatas、longranger2、cy-by-side、xiongsp、JeffersonHuang、Transmigration-zhou、magentaqin、Wonderdch、malone6、xiaomiusa87、gaofer、bluebean-cloud、a16su、Shyam-Chen、nanlei、hongyun-robot、Phoenix0415、MolDuM、Nigh、he-weilai、junminhong、mgisr、iron-irax、yd-j、XiaChuerwu、XC-Zero、seven1240、SamJin98、wodray、reeswell、NI-SW、Horbin-Magician、Enlightenus、xjr7670、YangXuanyi、DullSword、boloboloda、iStig、qq909244296、jiaxianhua、wenjianmin、keshida、kilikilikid、lclc6、lwbaptx、liuxjerry、lucaswangdev、lyl625760、hts0000、gledfish、fbigm、echo1937、szu17dmy、dshlstarr、Yucao-cy、coderlef、czruby、bongbongbakudan、beintentional、ZongYangL、ZhongYuuu、luluxia、xb534、bitsmi、ElaBosak233、baagod、zhouLion、yishangzhang、yi427、yabo083、weibk、wangwang105、th1nk3r-ing、tao363、4yDX3906、syd168、steventimes、sslmj2020、smilelsb、siqyka、selear、sdshaoda、Xi-Row、popozhu、nuquist19、noobcodemaker、XiaoK29、chadyi、ZhongGuanbin、shanghai-Jerry、JackYang-hellobobo、Javesun99、lipusheng、BlindTerran、ShiMaRing、FreddieLi、FloranceYeh、iFleey、fanchenggang、gltianwen、goerll、Dr-XYZ、nedchu、curly210102、CuB3y0nd、KraHsu、CarrotDLaw、youshaoXG、bubble9um、fanenr、eagleanurag、LifeGoesOnionOnionOnion、52coder、foursevenlove、KorsChen、hezhizhen、linzeyan、ZJKung、GaochaoZhu、hopkings2008、yang-le、Evilrabbit520、Turing-1024-Lee、thomasq0、Suremotoo、Allen-Scai、Risuntsy、Richard-Zhang1019、qingpeng9802、primexiao、nidhoggfgg、1ch0、MwumLi、martinx、ZnYang2018、hugtyftg、logan-qiu、psychelzh、Keynman、KeiichiKasai 和 0130w。
|
||||||
|
|
||||||
本書的程式碼審閱工作由 codingonion、curtishd、Gonglja、gvenusleo、hpstory、justin-tse、khoaxuantu、krahets、night-cruise、nuomi1 和 Reanon 完成(按照首字母順序排列)。感謝他們付出的時間與精力,正是他們確保了各語言程式碼的規範與統一。
|
本書的程式碼審閱工作由 coderonion、curtishd、Gonglja、gvenusleo、hpstory、justin-tse、khoaxuantu、krahets、night-cruise、nuomi1、Reanon 和 rongyi 完成(按照首字母順序排列)。感謝他們付出的時間與精力,正是他們確保了各語言程式碼的規範與統一。
|
||||||
|
|
||||||
在本書的創作過程中,我得到了許多人的幫助。
|
在本書的創作過程中,我得到了許多人的幫助。
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 74 KiB |
|
@ -155,7 +155,7 @@
|
||||||
<a href="https://github.com/krahets/hello-algo/releases">
|
<a href="https://github.com/krahets/hello-algo/releases">
|
||||||
<img class="device-on-hover" style="height: 75%;" src="../assets/hero/pdf_ipad.png" alt="">
|
<img class="device-on-hover" style="height: 75%;" src="../assets/hero/pdf_ipad.png" alt="">
|
||||||
<div class="text-button">
|
<div class="text-button">
|
||||||
<span>PDF(簡中)</span>
|
<span>下載 PDF</span>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
|
||||||
<path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z" />
|
<path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -258,9 +258,9 @@
|
||||||
<h3>程式碼審閱者</h3>
|
<h3>程式碼審閱者</h3>
|
||||||
<div class="profile-div">
|
<div class="profile-div">
|
||||||
<div class="profile-cell">
|
<div class="profile-cell">
|
||||||
<a href="https://github.com/codingonion">
|
<a href="https://github.com/coderonion">
|
||||||
<img class="profile-img" src="../assets/avatar/avatar_codingonion.jpg" alt="Reviewer: codingonion" />
|
<img class="profile-img" src="../assets/avatar/avatar_coderonion.jpg" alt="Reviewer: coderonion" />
|
||||||
<br><b>codingonion</b>
|
<br><b>coderonion</b>
|
||||||
<br><sub>Zig, Rust</sub>
|
<br><sub>Zig, Rust</sub>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ docs_dir: ../build/zh-hant/docs
|
||||||
site_dir: ../site/zh-hant
|
site_dir: ../site/zh-hant
|
||||||
# Repository
|
# Repository
|
||||||
edit_uri: tree/main/zh-hant/docs
|
edit_uri: tree/main/zh-hant/docs
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
theme:
|
theme:
|
||||||
|
|