Unify punctuation.

This commit is contained in:
krahets
2023-07-26 08:59:36 +08:00
parent 35973068a7
commit 63a0e73df0
46 changed files with 201 additions and 201 deletions

View File

@@ -8,9 +8,9 @@
考虑一个长度为 $n$ 的数组,元素是范围 $[0, 1)$ 的浮点数。桶排序的流程如下:
1. 初始化 $k$ 个桶,将 $n$ 个元素分配到 $k$ 个桶中
2. 对每个桶分别执行排序(本文采用编程语言的内置排序函数)
3. 按照桶的从小到大的顺序,合并结果
1. 初始化 $k$ 个桶,将 $n$ 个元素分配到 $k$ 个桶中
2. 对每个桶分别执行排序(本文采用编程语言的内置排序函数)
3. 按照桶的从小到大的顺序,合并结果
![桶排序算法流程](bucket_sort.assets/bucket_sort_overview.png)

View File

@@ -6,7 +6,7 @@
先来看一个简单的例子。给定一个长度为 $n$ 的数组 `nums` ,其中的元素都是“非负整数”。计数排序的整体流程如下:
1. 遍历数组,找出数组中的最大数字,记为 $m$ ,然后创建一个长度为 $m + 1$ 的辅助数组 `counter`
1. 遍历数组,找出数组中的最大数字,记为 $m$ ,然后创建一个长度为 $m + 1$ 的辅助数组 `counter`
2. **借助 `counter` 统计 `nums` 中各数字的出现次数**,其中 `counter[num]` 对应数字 `num` 的出现次数。统计方法很简单,只需遍历 `nums`(设当前数字为 `num`),每轮将 `counter[num]` 增加 $1$ 即可。
3. **由于 `counter` 的各个索引天然有序,因此相当于所有数字已经被排序好了**。接下来,我们遍历 `counter` ,根据各数字的出现次数,将它们按从小到大的顺序填入 `nums` 即可。
@@ -94,8 +94,8 @@ $$
**前缀和具有明确的意义,`prefix[num] - 1` 代表元素 `num` 在结果数组 `res` 中最后一次出现的索引**。这个信息非常关键,因为它告诉我们各个元素应该出现在结果数组的哪个位置。接下来,我们倒序遍历原数组 `nums` 的每个元素 `num` ,在每轮迭代中执行:
1. 将 `num` 填入数组 `res` 的索引 `prefix[num] - 1` 处
2. 令前缀和 `prefix[num]` 减小 $1$ ,从而得到下次放置 `num` 的索引
1. 将 `num` 填入数组 `res` 的索引 `prefix[num] - 1` 处
2. 令前缀和 `prefix[num]` 减小 $1$ ,从而得到下次放置 `num` 的索引
遍历完成后,数组 `res` 中就是排序好的结果,最后使用 `res` 覆盖原数组 `nums` 即可。

View File

@@ -2,17 +2,17 @@
「归并排序 Merge Sort」基于分治思想实现排序包含“划分”和“合并”两个阶段
1. **划分阶段**:通过递归不断地将数组从中点处分开,将长数组的排序问题转换为短数组的排序问题
2. **合并阶段**:当子数组长度为 1 时终止划分,开始合并,持续地将左右两个较短的有序数组合并为一个较长的有序数组,直至结束
1. **划分阶段**:通过递归不断地将数组从中点处分开,将长数组的排序问题转换为短数组的排序问题
2. **合并阶段**:当子数组长度为 1 时终止划分,开始合并,持续地将左右两个较短的有序数组合并为一个较长的有序数组,直至结束
![归并排序的划分与合并阶段](merge_sort.assets/merge_sort_overview.png)
## 算法流程
“划分阶段”从顶至底递归地将数组从中点切为两个子数组,直至长度为 1
“划分阶段”从顶至底递归地将数组从中点切为两个子数组
1. 计算数组中点 `mid` ,递归划分左子数组(区间 `[left, mid]` )和右子数组(区间 `[mid + 1, right]`
2. 递归执行步骤 `1.` ,直至子数组区间长度为 1 时,终止递归划分
1. 计算数组中点 `mid` ,递归划分左子数组(区间 `[left, mid]` )和右子数组(区间 `[mid + 1, right]`
2. 递归执行步骤 `1.` ,直至子数组区间长度为 1 时,终止递归划分
“合并阶段”从底至顶地将左子数组和右子数组合并为一个有序数组。需要注意的是,从长度为 1 的子数组开始合并,合并阶段中的每个子数组都是有序的。
@@ -155,6 +155,6 @@
归并排序在排序链表时具有显著优势,空间复杂度可以优化至 $O(1)$ ,原因如下:
- 由于链表仅需改变指针就可实现节点的增删操作,因此合并阶段(将两个短有序链表合并为一个长有序链表)无需创建辅助链表。
- 通过使用“迭代划分”替代“递归划分”,可省去递归使用的栈帧空间
- 通过使用“迭代划分”替代“递归划分”,可省去递归使用的栈帧空间
具体实现细节比较复杂,有兴趣的同学可以查阅相关资料进行学习。

View File

@@ -4,9 +4,9 @@
快速排序的核心操作是「哨兵划分」,其目标是:选择数组中的某个元素作为“基准数”,将所有小于基准数的元素移到其左侧,而大于基准数的元素移到其右侧。具体来说,哨兵划分的流程为:
1. 选取数组最左端元素作为基准数,初始化两个指针 `i``j` 分别指向数组的两端
2. 设置一个循环,在每轮中使用 `i``j`)分别寻找第一个比基准数大(小)的元素,然后交换这两个元素
3. 循环执行步骤 `2.` ,直到 `i``j` 相遇时停止,最后将基准数交换至两个子数组的分界线
1. 选取数组最左端元素作为基准数,初始化两个指针 `i``j` 分别指向数组的两端
2. 设置一个循环,在每轮中使用 `i``j`)分别寻找第一个比基准数大(小)的元素,然后交换这两个元素
3. 循环执行步骤 `2.` ,直到 `i``j` 相遇时停止,最后将基准数交换至两个子数组的分界线
哨兵划分完成后,原数组被划分成三部分:左子数组、基准数、右子数组,且满足“左子数组任意元素 $\leq$ 基准数 $\leq$ 右子数组任意元素”。因此,我们接下来只需对这两个子数组进行排序。
@@ -127,9 +127,9 @@
## 算法流程
1. 首先,对原数组执行一次「哨兵划分」,得到未排序的左子数组和右子数组
2. 然后,对左子数组和右子数组分别递归执行「哨兵划分」
3. 持续递归,直至子数组长度为 1 时终止,从而完成整个数组的排序
1. 首先,对原数组执行一次「哨兵划分」,得到未排序的左子数组和右子数组
2. 然后,对左子数组和右子数组分别递归执行「哨兵划分」
3. 持续递归,直至子数组长度为 1 时终止,从而完成整个数组的排序
![快速排序流程](quick_sort.assets/quick_sort_overview.png)

View File

@@ -8,9 +8,9 @@
以学号数据为例,假设数字的最低位是第 $1$ 位,最高位是第 $8$ 位,基数排序的步骤如下:
1. 初始化位数 $k = 1$
2. 对学号的第 $k$ 位执行「计数排序」。完成后,数据会根据第 $k$ 位从小到大排序
3. 将 $k$ 增加 $1$ ,然后返回步骤 `2.` 继续迭代,直到所有位都排序完成后结束
1. 初始化位数 $k = 1$
2. 对学号的第 $k$ 位执行「计数排序」。完成后,数据会根据第 $k$ 位从小到大排序
3. 将 $k$ 增加 $1$ ,然后返回步骤 `2.` 继续迭代,直到所有位都排序完成后结束
![基数排序算法流程](radix_sort.assets/radix_sort_overview.png)