diff --git a/docs/sop/notes/data-structure-algorithm-notes.md b/docs/sop/notes/data-structure-algorithm-notes.md
new file mode 100644
index 0000000..79531db
--- /dev/null
+++ b/docs/sop/notes/data-structure-algorithm-notes.md
@@ -0,0 +1,597 @@
+---
+title: 数据结构与算法笔记
+date: 2026-01-13
+descriptionHTML: '数据结构与算法详细复习及排序算法深度解析'
+tags:
+ - 笔记
+ - 数据结构
+ - 算法
+sidebar: true
+readingTime: true
+hidden: false
+recommend: true
+---
+
+# 数据结构与算法详细复习笔记
+
+## 第2章:线性表 (Linear List)
+
+### 1. 基本概念
+* **定义**:由 $n (n \ge 0)$ 个数据特性相同的元素构成的有限序列。
+ * **特性**:
+ * **有序性**:元素之间有逻辑上的顺序(第一个、最后一个、前驱、后继)。
+ * **有限性**:元素个数有限。
+* **抽象数据类型 (ADT)**:
+ * 数据对象:$D = \{a_i | a_i \in ElemSet, i=1, 2, ..., n\}$
+ * 数据关系:$R = \{ | a_{i-1}, a_i \in D, i=2, ..., n\}$
+ * 基本操作:`InitList`, `DestroyList`, `ListInsert`, `ListDelete`, `GetElem`, `LocateElem` 等。
+
+### 2. 顺序表 (Sequential List)
+* **定义**:用一组地址连续的存储单元依次存储线性表的数据元素。
+* **特点**:
+ * **随机存取**:通过首地址和下标可在 $O(1)$ 时间内访问任意元素。公式:$Loc(a_i) = Loc(a_1) + (i-1) \times L$。
+ * **存储密度高**:无需为逻辑关系(指针)额外分配空间。
+ * **缺点**:插入/删除需要移动大量元素(平均移动 $n/2$),需预分配空间(静态分配易溢出,动态分配需扩容)。
+
+### 3. 链表 (Linked List)
+* **单链表 (Singly Linked List)**:
+ * **结构**:结点 = 数据域 (data) + 指针域 (next)。
+ * **头结点**:在首元结点前附设的一个结点,便于处理空表和统一插入/删除操作。
+ * **建立方法**:
+ * **头插法**:新结点插入头结点之后,读入顺序与链表顺序相反(逆序)。
+ * **尾插法**:维护一个尾指针 `r`,新结点插在 `r` 之后,读入顺序与链表顺序相同。
+* **双向链表 (Doubly Linked List)**:
+ * **结构**:结点包含 `prior` (前驱) 和 `next` (后继) 指针。
+ * **插入操作** (`s` 插在 `p` 之后):
+ 1. `s->prior = p;`
+ 2. `s->next = p->next;`
+ 3. `p->next->prior = s;`
+ 4. `p->next = s;` (注意顺序,防止断链)
+ * **删除操作** (删除 `p` 的后继节点 `q`):
+ 1. `p->next = q->next;`
+ 2. `q->next->prior = p;`
+ 3. `free(q);`
+* **循环链表 (Circular Linked List)**:
+ * **特点**:表中最后一个结点的指针指向头结点,形成环状。
+ * **判空/遍历结束**:指针是否等于头指针 (or 尾指针)。
+ * **优势**:从任意结点出发均可遍历全表;若设尾指针 `rear`,则查找头尾的时间均为 $O(1)$(便于合并两个链表)。
+* **静态链表**:
+ * 利用数组实现,元素包含 `data` 和 `cur` (游标,即下个元素的数组下标)。
+ * 适用于不支持指针的语言(如 BASIC)或数据量固定且需频繁操作指针的场景。
+* **块状链表 (Unrolled Linked List)**:
+ * 每个结点存储多个数据元素(即一个小的顺序表)。平衡了顺序表(空间紧凑)和链表(插入删除快)的优缺点。
+
+### 4. 应用
+* **一元多项式相加**:利用链表按指数升序存储。遍历两个链表,比较指数大小:
+ * 指数相同:系数相加,若非零则保留。
+ * 指数不同:将指数小的项链入结果链表。
+* **大整数处理**:利用链表存储大整数的每一位(或每几位),便于进位处理。
+
+---
+
+## 第3章:栈与队列 (Stack & Queue)
+
+### 1. 栈 (Stack)
+* **定义**:只允许在表尾(栈顶 Top)进行插入(Push)和删除(Pop)的线性表。**LIFO** (Last In First Out)。
+* **实现**:
+ * **顺序栈**:`top` 指针指向栈顶元素(或栈顶上一个空位)。需判断 `StackOverflow` (上溢) 和 `StackUnderflow` (下溢,即空栈 pop)。
+ * **共享栈**:两个栈共享一段空间,栈底在两端,栈顶向中间延伸,`top1 + 1 == top2` 时满。
+* **应用**:
+ * **递归**:系统栈保存每一层调用的局部变量、返回地址。
+ * **括号匹配**:左括号压栈,右括号弹栈匹配。
+ * **表达式求值**:
+ * **中缀转后缀 (RPN)**:遇操作数输出;遇运算符与栈顶比较优先级。
+ * **后缀计算**:遇操作数压栈;遇运算符弹栈计算结果并压栈。
+ * **迷宫求解**:DFS 深度优先搜索(回溯法)。
+
+### 2. 队列 (Queue)
+* **定义**:只允许在表尾(Rear)插入,表头(Front)删除。**FIFO** (First In First Out)。
+* **循环队列 (Circular Queue)**:
+ * **问题**:顺序队列单纯 `front++` `rear++` 会导致“假溢出”(即前方有空位但 rear 已达上限)。
+ * **解决**:模运算。`(rear + 1) % MAXSIZE`。
+ * **判空/判满**:为了区分队空和队满,通常牺牲一个单元。
+ * **队空**:`front == rear`
+ * **队满**:`(rear + 1) % MAXSIZE == front`
+ * **队长**:`(rear - front + MAXSIZE) % MAXSIZE`
+* **双端队列 (Deque)**:两端均可入队、出队。
+ * **变种**:输入受限(一端入两端出)、输出受限(两端入一端出)。
+
+---
+
+## 第4章:字符串 (String)
+
+### 1. 基本概念
+* **串**:零个或多个字符组成的有限序列。
+* **子串**:主串中任意连续字符组成的子序列。
+* **存储**:定长顺序存储(截断)、堆分配存储(动态指针)、块链存储。
+
+### 2. 模式匹配算法
+* **朴素模式匹配 (Brute-Force)**:
+ * 主串指针 `i`,模式串指针 `j`。
+ * 失配时:`i` 回溯到 `i - j + 1`,`j` 回溯到 `0`。
+ * 最坏时间复杂度:$O(n \times m)$。
+* **KMP 算法 (Knuth-Morris-Pratt)**:
+ * **核心**:主串指针 `i` **不回溯**,模式串指针 `j` 回退到 `next[j]`。
+ * **Next 数组**:`next[j]` 表示模式串第 `j` 个字符前的子串中,**最长相等前后缀的长度**。
+ * 当 `S[i] != P[j]` 时,`j` 移动到 `next[j]` 继续比较。
+ * **NextVal 数组**(优化):若 `P[j] == P[next[j]]`,则递归优化,避免重复无效比较。
+ * 时间复杂度:$O(n + m)$。
+
+---
+
+## 第5章:数组和广义表
+
+### 1. 数组
+* **存储**:内存是一维的,多维数组需映射。
+ * **行优先 (Row-Major)**:C/C++。`LOC(a[i][j]) = LOC(0,0) + (i * n + j) * size`。
+ * **列优先 (Column-Major)**:Fortran。
+
+### 2. 矩阵压缩存储
+* **对称矩阵**:$a_{ij} = a_{ji}$。只存上三角或下三角。按行优先存储下三角元素 $(i \ge j)$ 的下标 $k = \frac{i(i+1)}{2} + j$。
+* **稀疏矩阵 (Sparse Matrix)**:
+ * **三元组表**:`(i, j, value)`。空间优化,但丧失随机存取特性。
+ * **十字链表**:每个非零元节点既在行链表上,又在列链表上。便于频繁插入删除。
+
+### 3. 广义表 (Generalized List)
+* **定义**:$LS = (a_1, a_2, ..., a_n)$,其中 $a_i$ 可以是原子或子表。
+* **重要操作**:
+ * **GetHead(L)**:取表头(第一个元素,可能是原子或列表)。
+ * **GetTail(L)**:取表尾(**除第一个元素外剩余元素构成的表**,结果一定是一个表)。
+ * *例*:$L=((a,b), c)$,Head(L)=$(a,b)$,Tail(L)=$(c)$。
+
+---
+
+## 第6章:树与二叉树
+
+### 1. 二叉树 (Binary Tree)
+* **性质**:
+ 1. 第 $i$ 层至多 $2^{i-1}$ 个结点。
+ 2. 深度为 $k$ 至多 $2^k - 1$ 个结点。
+ 3. **核心性质**:$n_0 = n_2 + 1$(叶子结点数 = 度为2的结点数 + 1)。
+* **完全二叉树 (Complete Binary Tree)**:
+ * 编号规则与满二叉树一一对应。
+ * 数组存储时,结点 $i$ 的左孩子为 $2i$,右孩子为 $2i+1$,父节点 $\lfloor i/2 \rfloor$。
+
+### 2. 遍历 (Traversal)
+* **前序 (Pre)**:根 -> 左 -> 右
+* **中序 (In)**:左 -> 根 -> 右
+* **后序 (Post)**:左 -> 右 -> 根
+* **层序**:利用**队列**实现 BFS。
+* **构造**:
+ * 前序 + 中序 -> 唯一确定二叉树。
+ * 后序 + 中序 -> 唯一确定二叉树。
+ * 前序 + 后序 -> **不能**唯一确定(无法区分左右子树)。
+
+### 3. 应用
+* **哈夫曼树 (Huffman Tree)**:
+ * **构造**:每次选取权值最小的两棵树合并,新树权值为两者之和,直到只剩一棵。
+ * **WPL (带权路径长度)**:$\sum (叶子权值 \times 路径长度)$。
+ * **哈夫曼编码**:前缀编码(任一字符编码都不是另一字符编码的前缀),用于数据压缩。
+* **线索二叉树**:
+ * 利用空闲指针域(`lchild`若空指向前驱,`rchild`若空指向后继),通过 `ltag/rtag` 标记。
+ * 加快遍历速度,无需递归或栈。
+
+---
+
+## 第7章:图 (Graph)
+
+### 1. 存储结构
+* **邻接矩阵**:`AdjMatrix[i][j] = 1` 或权值。
+ * 优点:易判断两点是否相连,易算度(行和列和)。
+ * 缺点:稀疏图浪费空间 $O(n^2)$。
+* **邻接表**:顶点表 + 边表(链表)。
+ * 优点:节省空间 $O(n+e)$。
+ * 缺点:求入度麻烦(需遍历全表或使用逆邻接表)。
+
+### 2. 遍历
+* **DFS (深度优先)**:类似树的先序遍历,使用**递归/栈**。
+* **BFS (广度优先)**:类似树的层序遍历,使用**队列**。最短路径特性(无权图)。
+
+---
+
+## 第8章:图的应用 (重难点)
+
+### 1. 最小生成树 (MST)
+* **Prim 算法**:
+ * **思想**:归并点。从一个顶点开始,每次选一条连接“已选集合”和“未选集合”且权值最小的边。
+ * **复杂度**:$O(n^2)$,适合**稠密图**。
+* **Kruskal 算法**:
+ * **思想**:归并边。将边按权值排序,从小到大选边,若不构成回路(利用并查集判断)则加入。
+ * **复杂度**:$O(e \log e)$,适合**稀疏图**。
+
+### 2. 最短路径
+* **Dijkstra 算法**:
+ * **单源最短路**。贪心策略。每次从未标记节点中选距离源点最近的节点,松弛其邻接点。
+ * **限制**:边权不能为负。
+ * **复杂度**:$O(n^2)$。
+* **Floyd 算法**:
+ * **多源最短路**。动态规划。`A[i][j] = min(A[i][j], A[i][k] + A[k][j])`。
+ * **复杂度**:$O(n^3)$。
+
+### 3. AOV 网与拓扑排序
+* **定义**:顶点表示活动,边表示优先关系。
+* **算法**:
+ 1. 选择入度为 0 的顶点输出。
+ 2. 删除该顶点及其出边。
+ 3. 重复直到图空或无入度为 0 的点(说明有环)。
+
+### 4. AOE 网与关键路径
+* **定义**:边表示活动,边权为持续时间,顶点表示事件。
+* **关键路径**:从源点到汇点的最长路径(决定工程最短工期)。
+* **计算**:
+ * 事件最早发生时间 `ve`(从前向后取max)。
+ * 事件最晚发生时间 `vl`(从后向前取min)。
+ * 活动最早/最晚开始时间 `e` / `l`。
+ * 若 `e == l`,则为关键活动。
+
+---
+
+## 第9章:查找 (Search)
+
+### 1. 动态查找树
+* **二叉排序树 (BST)**:左 < 根 < 右。中序遍历有序。插入/删除/查找平均 $O(\log n)$,最坏 $O(n)$(退化为链表)。
+* **平衡二叉树 (AVL)**:
+ * 任一节点左右子树高度差(平衡因子 BF)绝对值 $\le 1$。
+ * **调整**:
+ * **LL型**:右旋(Right Rotation)。
+ * **RR型**:左旋(Left Rotation)。
+ * **LR型**:先左旋后右旋。
+ * **RL型**:先右旋后左旋。
+
+### 2. 散列 (Hashing)
+* **散列函数**:`H(key)`。除留余数法 `H(key) = key % p` (p 为不大于表长的最大质数)。
+* **处理冲突**:
+ * **开放定址法**:
+ * 线性探测:`di = 1, 2, 3...` (易产生聚集/堆积现象)。
+ * 二次探测:`di = 1^2, -1^2, 2^2, -2^2...`。
+ * **链地址法**:相同 Hash 值的元素存入同一链表。
+* **ASL (平均查找长度)**:衡量效率指标,依赖于装填因子 $\alpha = \frac{填入元素个数}{表长}$。
+
+---
+
+## 第10章:排序 (Sorting)
+
+### 1. 算法复杂度与稳定性对比
+
+| 类别 | 排序算法 | 平均时间 | 最坏时间 | 空间 | 稳定性 | 备注 |
+| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
+| **插入** | **直接插入** | $O(n^2)$ | $O(n^2)$ | $O(1)$ | **稳定** | 适合基本有序/n较小 |
+| | **希尔排序** | $O(n^{1.3})$ | $O(n^2)$ | $O(1)$ | 不稳定 | 增量 $d$ 逐渐减半 |
+| **交换** | **冒泡排序** | $O(n^2)$ | $O(n^2)$ | $O(1)$ | **稳定** | 标志位优化 |
+| | **快速排序** | $O(n \log n)$ | $O(n^2)$ | $O(\log n)$ | 不稳定 | **内排序最快**,枢轴选择关键 |
+| **选择** | **简单选择** | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 不稳定 | 移动次数少 |
+| | **堆排序** | $O(n \log n)$ | $O(n \log n)$ | $O(1)$ | 不稳定 | 适合 Top K 问题 |
+| **归并** | **归并排序** | $O(n \log n)$ | $O(n \log n)$ | $O(n)$ | **稳定** | 空间换时间,外排序基础 |
+| **基数** | **基数排序** | $O(d(n+r))$ | $O(d(n+r))$ | $O(r)$ | **稳定** | 无需比较,分配+收集 |
+
+### 2. 核心算法说明
+* **快速排序 (Quick Sort)**:
+ * **Partition**:选取枢轴(pivot),将小于 pivot 的放左边,大于的放右边。
+ * 最坏情况:有序或逆序(退化为冒泡)。
+* **堆排序 (Heap Sort)**:
+ * **建堆**:从 $\lfloor n/2 \rfloor$ 处开始向下调整 (Heapify)。
+ * **排序**:交换堆顶与末尾元素,堆大小减1,重新向下调整。
+ * 升序排序使用**大顶堆**。
+* **归并排序**:
+ * Divide (分):将数组对半切分。
+ * Conquer (治):递归排序子数组。
+ * Merge (合):合并两个有序数组。
+
+---
+---
+
+## 附录:数据结构小测涉及公式与重点总结
+
+通过分析《小测1 答案》、《小测2 答案》及《小测3_题目答案》,以下是针对考试重点涉及的公式、推导及核心结论的详细总结。
+
+### 1. 栈与队列 (Stack & Queue)
+
+#### **卡特兰数 (Catalan Number)**
+* **应用场景**:$n$ 个不同元素进栈,可能的出栈序列总数。
+* **公式**:
+ $$C_n = \frac{1}{n+1} C_{2n}^n = \frac{(2n)!}{(n+1)!n!}$$
+* **小测案例** (小测1 第6题):
+ * $n=3$ 时,出栈序列数为 $C_3 = \frac{C_6^3}{4} = \frac{20}{4} = 5$ 种。
+
+#### **双端队列输出序列**
+* **排除法逻辑** (小测1 第8题):
+ * 对于输入受限或输出受限的双端队列,通常通过模拟和排除法来判断非法序列。
+ * *核心技巧*:结合栈的后进先出特性与队列的先进先出特性进行模拟。
+
+---
+
+### 2. 数组与矩阵 (Arrays & Matrices)
+
+#### **三对角矩阵压缩存储**
+* **定义**:元素仅分布在主对角线及上下两条对角线上。
+* **下标映射公式** (小测1 第10题):
+ * 题目特定映射关系:$A[1..n][1..n]$ 压缩至 $B[1..3n-2]$。
+ * 给定公式推导结果:$k = 2i + j - 2$。
+ * *案例验证*:$A[66][65]$ 对应 $k = 2 \times 66 + 65 - 2 = 195$。
+ * *注意*:通用公式通常为 $k = 2i + j - 3$ 或类似,考试时需严格根据题目给定的数组下标起始点(如从0还是从1开始)及排列方式进行推导。
+
+#### **KMP 算法 Next 数组计算**
+* **推导逻辑** (小测1 第13题):
+ * 若 $S[j] == S[k]$ (其中 $k = next[j-1]$),则 $next[j] = k + 1$。
+ * 若不等,则令 $k = next[k]$ 继续回溯比较。
+ * *案例*:$S = 'aaab'$
+ * $j=1, S='a', next[1]=0$ (固定)
+ * $j=2, S='a', S[1]==S[0]$? (前缀比较), $next[2]=1$
+ * $j=3, S='a', S[2]==S[1] \rightarrow next[3]=2$
+ * $j=4, S='b', S[3] \neq S[2]$, 回溯...
+
+---
+
+### 3. 树与二叉树 (Trees)
+
+#### **二叉树节点性质公式**
+1. **度数关系**:
+ * $$n_0 = n_2 + 1$$ (叶子结点数 = 度为2的结点数 + 1)
+ * 推导依据:
+ * 总节点数 $n = n_0 + n_1 + n_2$
+ * 总分支数 $B = n - 1 = n_1 + 2n_2$
+ * 联立消去 $n_1$,得 $n_0 = n_2 + 1$。
+ * *小测陷阱* (小测2 第1题):已知总数 $n=98$,$n_1=48$,求叶子数。
+ * $n_0 + 48 + n_2 = 98 \Rightarrow n_0 + n_2 = 50$
+ * 代入 $n_0 = n_2 + 1 \Rightarrow 2n_2 + 1 = 50 \Rightarrow 2n_2 = 49$。
+ * $n_2$ 必须为整数,故**不存在这样的树**。
+
+2. **完全二叉树 (Complete Binary Tree)**
+ * **叶子结点数**:$$n_0 = \lceil n/2 \rceil$$ (当 $n$ 为奇数时 $n_0 = (n+1)/2$,偶数时 $n_0 = n/2$)。
+ * *案例* (小测2 第3题):$n=47$ (奇数),$n_0 = (47+1)/2 = 24$。
+
+3. **哈夫曼树 (Huffman Tree)**
+ * **特性**:只有度为0和度为2的结点,**不存在度为1的结点** ($n_1 = 0$)。
+ * **节点总数公式**:
+ $$n = 2n_0 - 1$$
+ * *推导*:$n = n_0 + n_2$,且 $n_2 = n_0 - 1 \Rightarrow n = n_0 + (n_0 - 1) = 2n_0 - 1$。
+ * *小测结论* (小测2 第12题):若有 $n$ 个叶子结点(题目用 $n$ 表示 $n_0$),则总结点数为 $2n - 1$。
+
+4. **森林与树的转换**
+ * **连通分量/树的数量计算** (小测2 第9题):
+ * 若森林有 $N$ 个结点,$K$ 条边,则森林中树的棵数 $T$ 为:
+ $$T = N - K$$
+ * *推导*:每棵树 (连通分量) 的边数 = 节点数 - 1。设第 $i$ 棵树有 $v_i$ 个节点,则边数 $e_i = v_i - 1$。
+ * 总边数 $K = \sum (v_i - 1) = \sum v_i - \sum 1 = N - T \Rightarrow T = N - K$。
+
+---
+
+### 4. 图 (Graphs)
+
+#### **握手定理 (Handshaking Lemma)**
+* **公式**:所有顶点的度数之和等于边数的2倍。
+ $$\sum_{v \in V} \deg(v) = 2|E|$$
+* **最少顶点数求解** (小测3 第2题):
+ * 已知:$|E|=16$ (度数和32)。
+ * 已知点:3个度4,4个度3。已知度数和 $3 \times 4 + 4 \times 3 = 24$。
+ * 剩余度数:$32 - 24 = 8$。
+ * 约束:其余顶点度数 $<3$ (即最大为2)。
+ * 目标:顶点数最少 $\rightarrow$ 剩余顶点度数尽可能大 $\rightarrow$ 设其余点度数均为2。
+ * 剩余点数:$8 / 2 = 4$ 个。
+ * 总顶点数:$3 + 4 + 4 = 11$ 个。
+
+#### **最小生成树 (MST)**
+* **唯一性判定** (小测3 第8题):
+ * 当无向连通图的**最小生成树不唯一**时,Prim 和 Kruskal 算法生成的结果可能不同。
+ * 当最小生成树唯一时,两者结果必然相同。
+
+#### **关键路径 (Critical Path)**
+* **计算方法** (小测3 第11题):
+ * 路径长度 = 路径上所有活动(边)持续时间之和。
+ * 关键路径 = 源点到汇点的**最长路径**。
+ * *案例*:路径 $V_0 \rightarrow V_1 \rightarrow V_4 \rightarrow V_6 \rightarrow V_8$。
+ * 长度计算:$6 + 1 + 9 + 2 = 18$。
+
+
+
+## 排序算法深度解析 (Sorting Algorithms Deep Dive)
+
+本文档对常见的排序算法进行展开讲解,包含**核心思想**、**算法步骤**、**过程演示**、**复杂度分析**及**代码逻辑**。
+
+---
+
+### 1. 插入排序类 (Insertion Sorts)
+
+#### 1.1 直接插入排序 (Direct Insertion Sort)
+**核心思想**:
+将数组分为“已排序区间”和“未排序区间”。每次从未排序区间取出一个元素,在已排序区间中从后向前扫描,找到合适位置插入。类似于**抓扑克牌**的过程。
+
+**算法步骤**:
+1. 默认第 1 个元素已排序。
+2. 取出第 2 个元素 `temp`,与第 1 个比较。若 `temp < arr[1]`,则 `arr[1]` 后移,`temp` 插入开头。
+3. 重复直到所有元素归位。
+
+**过程演示** (排序 `[5, 2, 4, 6, 1, 3]`):
+* 初始:`[5]` | `2, 4, 6, 1, 3`
+* 取 2:2 比 5 小,5 后移。 -> `[2, 5]` | `4, 6, 1, 3`
+* 取 4:4 比 5 小,5 后移;4 比 2 大,停。 -> `[2, 4, 5]` | `6, 1, 3`
+* ...以此类推。
+
+**核心代码逻辑 (C/C++)**:
+```c
+void InsertSort(int A[], int n) {
+ int i, j, temp;
+ for (i = 1; i < n; i++) { // 从第2个元素开始
+ if (A[i] < A[i-1]) { // 若小于前驱,需插入
+ temp = A[i]; // 暂存当前元素
+ for (j = i-1; j >= 0 && A[j] > temp; --j) {
+ A[j+1] = A[j]; // 大于temp的元素后移
+ }
+ A[j+1] = temp; // 插入
+ }
+ }
+}
+```
+
+**分析**:
+* **最好情况**:$O(n)$(已是有序,只需比较不移动)。
+* **最坏情况**:$O(n^2)$(逆序)。
+* **稳定性**:**稳定**(因为 `A[j] > temp` 才移动,相等时不移动)。
+
+---
+
+#### 1.2 希尔排序 (Shell Sort)
+**核心思想**:
+又称“**缩小增量排序**”。是直接插入排序的优化版。通过将数组按增量 `d` 分组,对每组进行直接插入排序,使数组“基本有序”,最后 `d=1` 时再进行一次直接插入。
+
+**为什么比直接插入快?**
+直接插入在基本有序时效率极高。希尔排序前期移动步长长,能快速消除逆序对;后期步长短但数组已基本有序,移动次数少。
+
+**过程演示**:
+数组 `[8, 9, 1, 7, 2, 3, 5, 4, 6, 0]`,$n=10$。
+1. **d=5** (分5组: `8,3`, `9,5`, `1,4`, `7,6`, `2,0`):
+ * 组内排序后 -> `[3, 5, 1, 6, 0, 8, 9, 4, 7, 2]`
+2. **d=2** (分2组: `3,1,0,9,7`, `5,6,8,4,2`):
+ * 组内排序后 -> `[0, 2, 1, 4, 3, 5, 7, 6, 9, 8]`
+3. **d=1** (整体直接插入):
+ * 微调 -> `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`
+
+**分析**:
+* **复杂度**:依赖于增量序列,平均约 $O(n^{1.3})$。
+* **稳定性**:**不稳定**(相同元素可能分在不同组,跳跃式移动导致相对位置改变)。
+
+---
+
+### 2. 交换排序类 (Exchange Sorts)
+
+#### 2.1 冒泡排序 (Bubble Sort)
+**核心思想**:
+两两比较相邻记录,如果反序则交换,直到没有反序的记录为止。每趟遍历将最大的元素“浮”到最后(或最小的“沉”到最前)。
+
+**优化点**:
+设置 `flag` 变量。若某一趟遍历中**没有发生任何交换**,说明已经有序,直接结束算法。
+
+**分析**:
+* **最好情况**:$O(n)$(有序,第一趟 `flag` 未变直接退出)。
+* **最坏情况**:$O(n^2)$。
+* **稳定性**:**稳定**。
+
+---
+
+#### 2.2 快速排序 (Quick Sort) —— **最重要的排序算法**
+**核心思想**:
+**分治法 (Divide and Conquer)**。
+1. **选基准 (Pivot)**:通常选第一个元素。
+2. **划分 (Partition)**:将比基准小的移到左边,比基准大的移到右边。基准归位。
+3. **递归**:对左右两个子序列重复上述过程。
+
+**Partition 过程详解 (双指针法)**:
+设基准 `pivot = A[low]`,`low` 指向首,`high` 指向尾。
+1. **High 向左找小**:`while (low < high && A[high] >= pivot) high--;` 找到比 pivot 小的,移到 `low` 处 (`A[low] = A[high]`)。
+2. **Low 向右找大**:`while (low < high && A[low] <= pivot) low++;` 找到比 pivot 大的,移到 `high` 处 (`A[high] = A[low]`)。
+3. 重复直到 `low == high`,将 `pivot` 放入 `A[low]`。
+
+**代码片段**:
+```c
+int Partition(int A[], int low, int high) {
+ int pivot = A[low]; // 选第一个为基准
+ while (low < high) {
+ while (low < high && A[high] >= pivot) high--;
+ A[low] = A[high];
+ while (low < high && A[low] <= pivot) low++;
+ A[high] = A[low];
+ }
+ A[low] = pivot;
+ return low; // 返回基准位置
+}
+```
+
+**分析**:
+* **平均复杂度**:$O(n \log n)$。
+* **最坏复杂度**:$O(n^2)$。发生在**有序**或**逆序**时,基准每次都选到最大/最小,退化为冒泡。
+* **空间复杂度**:$O(\log n)$ (递归栈的高度)。
+* **稳定性**:**不稳定**(Partition 过程中的远距离交换)。
+
+---
+
+### 3. 选择排序类 (Selection Sorts)
+
+#### 3.1 简单选择排序 (Simple Selection Sort)
+**核心思想**:
+第 $i$ 趟从 $A[i...n]$ 中选出最小的元素,与 $A[i]$ 交换。
+
+**特点**:
+* **交换次数少**:最多 $n-1$ 次(优于冒泡)。
+* **比较次数多**:固定 $\frac{n(n-1)}{2}$ 次。
+* **稳定性**:**不稳定**。
+ * *例子*:`[5, 8, 5, 2, 9]`。第一趟,第一个 `5` 会和 `2` 交换,跑到第二个 `5` 后面。
+
+---
+
+#### 3.2 堆排序 (Heap Sort)
+**核心思想**:
+利用**堆**(完全二叉树)这种数据结构。
+* **大顶堆**:$A[i] \ge A[2i+1]$ 且 $A[i] \ge A[2i+2]$。用于**升序**排序。
+* **小顶堆**:用于降序排序。
+
+**算法步骤**:
+1. **建堆**:将无序数组构造成一个大顶堆。
+ * 从最后一个非叶子结点 ($\lfloor n/2 \rfloor - 1$) 开始,从右至左,从下至上进行“下沉”调整 (`HeapAdjust` / `sift_down`)。
+2. **排序**:
+ * 将堆顶元素(最大值)与堆底末尾元素交换。
+ * 将剩余 $n-1$ 个元素重新调整为大顶堆。
+ * 重复直至堆大小为 1。
+
+**下沉 (sift_down) 逻辑**:
+判断节点 `k`,其左孩子 `2k+1`,右孩子 `2k+2`。
+若孩子比父节点大,则将最大的孩子与父节点交换,并继续向下追踪被交换的孩子节点。
+
+**分析**:
+* **复杂度**:$O(n \log n)$。建堆 $O(n)$,调整 $O(n \log n)$。
+* **优势**:在 Top K 问题(选出前 K 大)中表现极佳。
+* **稳定性**:**不稳定**。
+
+---
+
+### 4. 归并排序 (Merge Sort)
+
+**核心思想**:
+**分治法**。
+1. **分**:将数组从中间切开,递归切分,直到长度为 1。
+2. **治 (Merge)**:将两个**有序**的子数组合并成一个有序数组。
+
+**Merge 过程**:
+需申请一个辅助数组 `B[]`。
+比较左半区 `A[i]` 和右半区 `A[j]`:
+* 若 `A[i] <= A[j]`,将 `A[i]` 放入 `B`,`i++`。
+* 若 `A[i] > A[j]`,将 `A[j]` 放入 `B`,`j++`。
+* 最后将剩余元素复制进 `B`,再把 `B` 拷回 `A`。
+
+**分析**:
+* **复杂度**:$O(n \log n)$。
+* **空间复杂度**:$O(n)$(需要辅助数组,这是它最大的缺点)。
+* **稳定性**:**稳定**(Merge 时 `A[i] <= A[j]` 优先取左边,保证相对位置不变)。
+
+---
+
+### 5. 基数排序 (Radix Sort)
+
+**核心思想**:
+**不基于比较**的排序。利用“分配”和“收集”。
+通常针对非负整数。将整数按位数切割成不同的数字,按每个位数分别比较。
+
+**步骤 (LSD - Least Significant Digit)**:
+1. **按个位排序**:准备 10 个桶 (0-9)。遍历数组,按个位数字放入对应桶。按顺序收集回来。
+2. **按十位排序**:基于上一步结果,按十位放入桶,再收集。
+3. ...直至最高位。
+
+**分析**:
+* **复杂度**:$O(d(n+r))$。
+ * $d$:最大数字的位数(决定遍历几趟)。
+ * $n$:元素个数。
+ * $r$:基数(如十进制 r=10,决定桶的个数)。
+* **稳定性**:**稳定**(必须稳定,否则高位排序会打乱低位的顺序)。
+
+---
+
+### 6. 总结对比表
+
+| 算法 | 平均时间 | 最好 | 最坏 | 空间 | 稳定性 | 关键词 |
+| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
+| **直接插入** | $O(n^2)$ | $O(n)$ | $O(n^2)$ | $O(1)$ | **稳定** | 摸牌、越有序越快 |
+| **希尔** | $O(n^{1.3})$ | - | $O(n^2)$ | $O(1)$ | 不稳定 | 增量分组 |
+| **冒泡** | $O(n^2)$ | $O(n)$ | $O(n^2)$ | $O(1)$ | **稳定** | 交换、flag优化 |
+| **快速** | $O(n \log n)$ | $O(n \log n)$ | $O(n^2)$ | $O(\log n)$ | 不稳定 | **Partition**、分治 |
+| **简单选择** | $O(n^2)$ | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 不稳定 | 选最小 |
+| **堆排序** | $O(n \log n)$ | $O(n \log n)$ | $O(n \log n)$ | $O(1)$ | 不稳定 | **建堆**、下沉 |
+| **归并** | $O(n \log n)$ | $O(n \log n)$ | $O(n \log n)$ | $O(n)$ | **稳定** | **合并**、空间换时间 |