mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-05 11:41:22 +08:00
build
This commit is contained in:
@@ -9,25 +9,25 @@ comments: true
|
||||
如图 11-4 所示,冒泡过程可以利用元素交换操作来模拟:从数组最左端开始向右遍历,依次比较相邻元素大小,如果“左元素 > 右元素”就交换它俩。遍历完成后,最大的元素会被移动到数组的最右端。
|
||||
|
||||
=== "<1>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<2>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<3>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<4>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<5>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<6>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<7>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-4 利用元素交换操作模拟冒泡 </p>
|
||||
|
||||
@@ -40,7 +40,7 @@ comments: true
|
||||
3. 以此类推,经过 $n - 1$ 轮“冒泡”后,**前 $n - 1$ 大的元素都被交换至正确位置**。
|
||||
4. 仅剩的一个元素必定是最小元素,无须排序,因此数组排序完成。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-5 冒泡排序流程 </p>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ comments: true
|
||||
2. 对每个桶分别执行排序(本文采用编程语言的内置排序函数)。
|
||||
3. 按照桶的从小到大的顺序,合并结果。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-13 桶排序算法流程 </p>
|
||||
|
||||
@@ -409,7 +409,7 @@ comments: true
|
||||
|
||||
如图 11-14 所示,这种方法本质上是创建一个递归树,目标是让叶节点的值尽可能平均。当然,不一定要每轮将数据划分为 3 个桶,具体划分方式可根据数据特点灵活选择。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-14 递归划分桶 </p>
|
||||
|
||||
@@ -417,6 +417,6 @@ comments: true
|
||||
|
||||
如图 11-15 所示,我们假设商品价格服从正态分布,这样就可以合理地设定价格区间,从而将商品平均分配到各个桶中。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-15 根据概率分布划分桶 </p>
|
||||
|
||||
@@ -14,7 +14,7 @@ comments: true
|
||||
2. **借助 `counter` 统计 `nums` 中各数字的出现次数**,其中 `counter[num]` 对应数字 `num` 的出现次数。统计方法很简单,只需遍历 `nums`(设当前数字为 `num`),每轮将 `counter[num]` 增加 $1$ 即可。
|
||||
3. **由于 `counter` 的各个索引天然有序,因此相当于所有数字已经被排序好了**。接下来,我们遍历 `counter` ,根据各数字的出现次数,将它们按从小到大的顺序填入 `nums` 即可。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-16 计数排序流程 </p>
|
||||
|
||||
@@ -339,28 +339,28 @@ $$
|
||||
遍历完成后,数组 `res` 中就是排序好的结果,最后使用 `res` 覆盖原数组 `nums` 即可。图 11-17 展示了完整的计数排序流程。
|
||||
|
||||
=== "<1>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<2>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<3>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<4>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<5>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<6>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<7>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<8>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-17 计数排序步骤 </p>
|
||||
|
||||
|
||||
@@ -29,40 +29,40 @@ comments: true
|
||||
实际上,元素出堆操作中也包含第 `2.` 和 `3.` 步,只是多了一个弹出元素的步骤。
|
||||
|
||||
=== "<1>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<2>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<3>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<4>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<5>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<6>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<7>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<8>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<9>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<10>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<11>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<12>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-12 堆排序步骤 </p>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ icon: material/sort-ascending
|
||||
|
||||
<div class="center-table" markdown>
|
||||
|
||||
{ width="600" }
|
||||
{ class="cover-image" }
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ comments: true
|
||||
|
||||
图 11-6 展示了数组插入元素的操作流程。设基准元素为 `base` ,我们需要将从目标索引到 `base` 之间的所有元素向右移动一位,然后再将 `base` 赋值给目标索引。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-6 单次插入操作 </p>
|
||||
|
||||
@@ -23,7 +23,7 @@ comments: true
|
||||
3. 选取第 3 个元素作为 `base` ,将其插入到正确位置后,**数组的前 3 个元素已排序**。
|
||||
4. 以此类推,在最后一轮中,选取最后一个元素作为 `base` ,将其插入到正确位置后,**所有元素均已排序**。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-7 插入排序流程 </p>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ comments: true
|
||||
1. **划分阶段**:通过递归不断地将数组从中点处分开,将长数组的排序问题转换为短数组的排序问题。
|
||||
2. **合并阶段**:当子数组长度为 1 时终止划分,开始合并,持续地将左右两个较短的有序数组合并为一个较长的有序数组,直至结束。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-10 归并排序的划分与合并阶段 </p>
|
||||
|
||||
@@ -23,34 +23,34 @@ comments: true
|
||||
“合并阶段”从底至顶地将左子数组和右子数组合并为一个有序数组。需要注意的是,从长度为 1 的子数组开始合并,合并阶段中的每个子数组都是有序的。
|
||||
|
||||
=== "<1>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<2>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<3>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<4>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<5>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<6>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<7>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<8>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<9>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<10>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-11 归并排序步骤 </p>
|
||||
|
||||
|
||||
@@ -13,31 +13,31 @@ comments: true
|
||||
3. 循环执行步骤 `2.` ,直到 `i` 和 `j` 相遇时停止,最后将基准数交换至两个子数组的分界线。
|
||||
|
||||
=== "<1>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<2>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<3>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<4>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<5>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<6>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<7>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<8>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<9>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-8 哨兵划分步骤 </p>
|
||||
|
||||
@@ -366,7 +366,7 @@ comments: true
|
||||
2. 然后,对左子数组和右子数组分别递归执行“哨兵划分”。
|
||||
3. 持续递归,直至子数组长度为 1 时终止,从而完成整个数组的排序。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-9 快速排序流程 </p>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ comments: true
|
||||
2. 对学号的第 $k$ 位执行“计数排序”。完成后,数据会根据第 $k$ 位从小到大排序。
|
||||
3. 将 $k$ 增加 $1$ ,然后返回步骤 `2.` 继续迭代,直到所有位都排序完成后结束。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-18 基数排序算法流程 </p>
|
||||
|
||||
|
||||
@@ -15,37 +15,37 @@ comments: true
|
||||
5. 仅剩的一个元素必定是最大元素,无须排序,因此数组排序完成。
|
||||
|
||||
=== "<1>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<2>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<3>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<4>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<5>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<6>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<7>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<8>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<9>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<10>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "<11>"
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-2 选择排序步骤 </p>
|
||||
|
||||
@@ -290,6 +290,6 @@ comments: true
|
||||
- **空间复杂度 $O(1)$、原地排序**:指针 $i$ 和 $j$ 使用常数大小的额外空间。
|
||||
- **非稳定排序**:如图 11-3 所示,元素 `nums[i]` 有可能被交换至与其相等的元素的右边,导致两者相对顺序发生改变。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-3 选择排序非稳定示例 </p>
|
||||
|
||||
@@ -8,7 +8,7 @@ comments: true
|
||||
|
||||
如图 11-1 所示,排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定,如数字大小、字符 ASCII 码顺序或自定义规则。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-1 数据类型和判断规则示例 </p>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ comments: true
|
||||
- 总的来说,我们希望找到一种排序算法,具有高效率、稳定、原地以及正向自适应性等优点。然而,正如其他数据结构和算法一样,没有一种排序算法能够同时满足所有这些条件。在实际应用中,我们需要根据数据的特性来选择合适的排序算法。
|
||||
- 图 11-19 对比了主流排序算法的效率、稳定性、就地性和自适应性等。
|
||||
|
||||

|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> 图 11-19 排序算法对比 </p>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user