This commit is contained in:
krahets
2023-08-20 14:52:31 +08:00
parent 44a8568356
commit 68e11cfa34
40 changed files with 239 additions and 235 deletions

View File

@@ -38,7 +38,7 @@ comments: true
1. 首先,对 $n$ 个元素执行“冒泡”,**将数组的最大元素交换至正确位置**
2. 接下来,对剩余 $n - 1$ 个元素执行“冒泡”,**将第二大元素交换至正确位置**。
3. 以此类推,经过 $n - 1$ 轮“冒泡”后,**前 $n - 1$ 大的元素都被交换至正确位置**。
4. 仅剩的一个元素必定是最小元素,无排序,因此数组排序完成。
4. 仅剩的一个元素必定是最小元素,无排序,因此数组排序完成。
![冒泡排序流程](bubble_sort.assets/bubble_sort_overview.png)

View File

@@ -80,7 +80,7 @@ comments: true
ma = l;
if (r < n && nums[r] > nums[ma])
ma = r;
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma == i)
break;
// 交换两节点
@@ -124,7 +124,7 @@ comments: true
ma = l;
if (r < n && nums[r] > nums[ma])
ma = r;
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma == i) {
break;
}
@@ -165,7 +165,7 @@ comments: true
ma = l
if r < n and nums[r] > nums[ma]:
ma = r
# 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
# 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if ma == i:
break
# 交换两节点
@@ -202,7 +202,7 @@ comments: true
if r < n && (*nums)[r] > (*nums)[ma] {
ma = r
}
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if ma == i {
break
}
@@ -245,7 +245,7 @@ comments: true
if (r < n && nums[r] > nums[ma]) {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma === i) {
break;
}
@@ -288,7 +288,7 @@ comments: true
if (r < n && nums[r] > nums[ma]) {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma === i) {
break;
}
@@ -329,7 +329,7 @@ comments: true
ma = l;
if (r < n && nums[r] > nums[ma])
ma = r;
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma == i) {
break;
}
@@ -374,7 +374,7 @@ comments: true
ma = l;
if (r < n && nums[r] > nums[ma])
ma = r;
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma == i)
break;
// 交换两节点
@@ -417,7 +417,7 @@ comments: true
if r < n, nums[r] > nums[ma] {
ma = r
}
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if ma == i {
break
}
@@ -464,7 +464,7 @@ comments: true
int ma = i;
if (l < n && nums[l] > nums[ma]) ma = l;
if (r < n && nums[r] > nums[ma]) ma = r;
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if (ma == i) break;
// 交换两节点
int temp = nums[i];
@@ -509,7 +509,7 @@ comments: true
if r < n && nums[r] > nums[ma] {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
// 若节点 i 最大或索引 l, r 越界,则无继续堆化,跳出
if ma == i {
break;
}

View File

@@ -258,7 +258,7 @@ comments: true
插入排序的时间复杂度为 $O(n^2)$ ,而我们即将学习的快速排序的时间复杂度为 $O(n \log n)$ 。尽管插入排序的时间复杂度相比快速排序更高,**但在数据量较小的情况下,插入排序通常更快**。
这个结论与线性查找和二分查找的适用情况的结论类似。快速排序这类 $O(n \log n)$ 的算法属于基于分治的排序算法,往往包含更多单元计算操作。而在数据量较小时,$n^2$ 和 $n \log n$ 的数值比较接近,复杂度不占主导作用;每轮中的单元计算操作数量起到决定性因素。
这个结论与线性查找和二分查找的适用情况的结论类似。快速排序这类 $O(n \log n)$ 的算法属于基于分治的排序算法,往往包含更多单元计算操作。而在数据量较小时,$n^2$ 和 $n \log n$ 的数值比较接近,复杂度不占主导作用;每轮中的单元操作数量起到决定性因素。
实际上,许多编程语言(例如 Java的内置排序函数都采用了插入排序大致思路为对于长数组采用基于分治的排序算法例如快速排序对于短数组直接使用插入排序。

View File

@@ -635,7 +635,7 @@ comments: true
归并排序在排序链表时具有显著优势,空间复杂度可以优化至 $O(1)$ ,原因如下:
- 由于链表仅需改变指针就可实现节点的增删操作,因此合并阶段(将两个短有序链表合并为一个长有序链表)无创建辅助链表。
- 由于链表仅需改变指针就可实现节点的增删操作,因此合并阶段(将两个短有序链表合并为一个长有序链表)无创建辅助链表。
- 通过使用“迭代划分”替代“递归划分”,可省去递归使用的栈帧空间。
具体实现细节比较复杂,有兴趣的同学可以查阅相关资料进行学习。

View File

@@ -12,7 +12,7 @@ comments: true
2. 选取区间 $[0, n-1]$ 中的最小元素,将其与索引 $0$ 处元素交换。完成后,数组前 1 个元素已排序。
3. 选取区间 $[1, n-1]$ 中的最小元素,将其与索引 $1$ 处元素交换。完成后,数组前 2 个元素已排序。
4. 以此类推。经过 $n - 1$ 轮选择与交换后,数组前 $n - 1$ 个元素已排序。
5. 仅剩的一个元素必定是最大元素,无排序,因此数组排序完成。
5. 仅剩的一个元素必定是最大元素,无排序,因此数组排序完成。
=== "<1>"
![选择排序步骤](selection_sort.assets/selection_sort_step1.png)

View File

@@ -16,7 +16,7 @@ comments: true
**运行效率**:我们期望排序算法的时间复杂度尽量低,且总体操作数量较少(即时间复杂度中的常数项降低)。对于大数据量情况,运行效率显得尤为重要。
**就地性**:顾名思义,「原地排序」通过在原数组上直接操作实现排序,无借助额外的辅助数组,从而节省内存。通常情况下,原地排序的数据搬运操作较少,运行速度也更快。
**就地性**:顾名思义,「原地排序」通过在原数组上直接操作实现排序,无借助额外的辅助数组,从而节省内存。通常情况下,原地排序的数据搬运操作较少,运行速度也更快。
**稳定性**:「稳定排序」在完成排序后,相等元素在数组中的相对顺序不发生改变。稳定排序是优良特性,也是多级排序场景的必要条件。