
⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///
WARNING \]: DETECTING HIGH ENERGY **🌊 🌉 🌊 心手合一 · 水到渠成**  |------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | **\>\>\> ACCESS TERMINAL \<\<\<** || | [**\[ 🦾 作者主页 \]**](https://blog.csdn.net/fengtinghuqu520?spm=1000.2115.3001.5343) | [**\[ 🔥 C语言核心 \]**](https://blog.csdn.net/fengtinghuqu520/category_12955956.html) | | [**\[ 💾 编程百度 \]**](https://blog.csdn.net/fengtinghuqu520/category_13083835.html) | [**\[ 📡 代码仓库 \]**](https://blog.csdn.net/fengtinghuqu520/article/details/147275999?spm=1001.2014.3001.5502) | --------------------------------------- Running Process: 100% \| Latency: 0ms *** ** * ** *** #### 索引与导读 * ["堆"数据结构的复习](#“堆”数据结构的复习) * [堆排序的核心逻辑](#堆排序的核心逻辑) * [向下调整的算法](#向下调整的算法) * * [🔥🔥🔥🔥代码解析](#🔥🔥🔥🔥代码解析) * [堆排序代码实现](#堆排序代码实现) * [🔨关于测试堆排序的分文件代码](#🔨关于测试堆排序的分文件代码) * [💻结尾--- 核心连接协议](#💻结尾— 核心连接协议) ## "堆"数据结构的复习 > 🔗[Lucy的空间骇客裂缝:堆](https://blog.csdn.net/fengtinghuqu520/article/details/156204209?spm=1011.2415.3001.5331) * **什么是"堆" (Heap)?** 堆通常是一个可以被看做一棵**完全二叉树**的数组对象,也就是二叉树的顺序存储 * **逻辑上**:它是一棵完全二叉树 * **物理上** :它存储在一个连续的数组中 * **大顶堆与小顶堆** * **大顶堆 (Max Heap)** :每个节点的值都**大于或等于** 其左右孩子节点的值。 * **数学定义** : a r r \[ i \] ≥ a r r \[ 2 i + 1 \] arr\[i\] \\ge arr\[2i+1\] arr\[i\]≥arr\[2i+1\] 且 a r r \[ i \] ≥ a r r \[ 2 i + 2 \] arr\[i\] \\ge arr\[2i+2\] arr\[i\]≥arr\[2i+2
* **特性** :堆顶元素(数组首元素)是整个序列中的**最大值**。
-
小顶堆 (Min Heap) :每个节点的值都小于或等于 其左右孩子节点的值。
- 特性 :堆顶元素是整个序列中的最小值。
-
数组下标与树的关系
对于数组中任意位置 i i i 的元素(从0开始索引),其在逻辑二叉树中的关系如下:
- 父节点 (Parent) 的下标: ⌊ ( i − 1 ) / 2 ⌋ \lfloor (i - 1) / 2 \rfloor ⌊(i−1)/2⌋
- 左孩子 (Left Child) 的下标: 2 × i + 1 2 \times i + 1 2×i+1
- 右孩子 (Right Child) 的下标: 2 × i + 2 2 \times i + 2 2×i+2
注意 :我们在进行升序排序 (从小到大)时,通常使用大顶堆 ;进行降序排序时,使用小顶堆
堆排序的核心逻辑
堆排序主要分为两个核心阶段:
- 建堆 (Build Heap) :将一个无序数组调整为一个大顶堆 或者小顶堆
- 升序:建大堆
- 降序:建小堆
- 排序 (Sort) :
建堆和堆删除中都用到了向下调整 ,因此掌握了向下调整,就可以完成堆排序- 将堆顶元素(最大值)与数组末尾元素交换。
- 将数组长度减
1(排除已排序的末尾元素)。 - 对剩下的元素重新进行向下调整 ,使其再次满足大顶堆性质。
- 重复上述过程,直到堆的大小为
1
堆排序 Heap Sort
核心基础
向下调整 Downward Adjustment
注: 建堆和排序的关键通用技术
第一阶段: 建堆 Build Heap
描述
将无序数组调整为堆结构
策略选择
升序排序
--> 建大顶堆 Max-Heap
降序排序
--> 建小顶堆 Min-Heap
第二阶段: 排序循环 Sorting Loop
前提: 已建成大顶堆/小顶堆
循环步骤
- 交换 Swap 堆顶最大值 <--> 数组末尾元素
- 缩小范围 Reduce Scope 数组有效长度减 1, 排除已排序元素
- 恢复堆性 Restore 对剩余元素重新向下调整
终止条件
循环直到堆大小 = 1
向下调整的算法
本次代码将综合堆数据结构 来实现
c
void AdjustDown(HP* php, int parent) {
assert(php);
int child = parent * 2 + 1; // 默认先指向左孩子
while (child < php->size) {
// 1. 在左右孩子中选出更"优"的一个
if (child + 1 < php->size && php->cmp(php->arr[child + 1], php->arr[child])) {
child++;
}
// 2. 如果选出的孩子比父节点更"优",则交换
if (php->cmp(php->arr[child], php->arr[parent])) {
Swap(&php->arr[child], &php->arr[parent]);
parent = child;
child = parent * 2 + 1;
}
else {
break;
}
}
}
🔥🔥🔥🔥代码解析
函数声明
void AdjustDown(HP* php, int parent)
HP* php:指向堆结构的指针int parent:开始调整的父节点索引- 用于将
parent节点调整到合适位置,保持堆的性质
计算左孩子索引
int child = parent * 2 + 1
-
堆是完全二叉树,通常用数组存储
-
数组下标从
0开始的父子关系公式:-
左孩子 = 父节点 × 2 + 1
-
右孩子 = 父节点 × 2 + 2
-
-
这里先假设左孩子是需要比较的孩子
循环条件
while (child < php->size)
- 只要
child索引在堆的有效范围内就继续循环
选择更"优"的孩子
if (child + 1 < php->size && php->cmp(php->arr[child + 1], php->arr[child])) {child++;}
child + 1 < php->size:检查右孩子是否存在
- 如果
child+1小于size,说明有右孩子
php->cmp(php->arr[child + 1], php->arr[child]):
-
调用比较函数比较右孩子和左孩子
-
这个比较函数决定了是最大堆 还是最小堆:
- 最大堆:返回a > b
- 最小堆:返回a < b
-
如果右孩子更"优"(在大顶堆中更大,在小顶堆中更小),则
child++指向右孩子
经过这个判断,child指向左右孩子中更"优"的那个
与父节点比较并交换

-
比较选出的孩子和父节点
- 如果孩子更"优"(需要交换)
-
交换父节点和孩子节点的值
Swap函数交换两个元素
-
更新索引,继续向下调整
-
parent = child:父节点下移到刚才交换的位置 -
child = parent * 2 + 1:重新计算新的左孩子索引 -
继续下一轮循环
-
堆排序代码实现
本次代码将综合堆数据结构 来实现
注意编写前需要在头文件进行声明!
c
void HeapSort(int* a, int n) {
// 1. 建大堆 (从最后一个非叶子节点开始)
for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
AdjustDown(a, n, i);
}
// 2. 交换与调整
int end = n - 1;
while (end > 0) {
Swap(&a[0], &a[end]); // 将堆顶最大元素换到数组末尾
AdjustDown(a, end, 0); // 在剩余 [0, end-1] 范围内向下调整
end--;
}
}
建堆阶段
(n - 1 - 1) / 2
- 最后一个非叶子节点的索引公式:
(最后一个元素索引 - 1) / 2
排序阶段
Swap(&a[0], &a[end]);
- 将堆顶最大元素换到数组末尾
AdjustDown(a, end, 0)
- 在剩余
[0, end-1]范围内向下调整
🔨关于测试堆排序的分文件代码
💻结尾--- 核心连接协议
警告: 🌠🌠正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层,请执行以下指令序列以同步数据:🌠🌠
【📡】 建立深度链接: 关注本终端。在赛博丛林中深耕底层架构,从原始代码到进阶协议,同步见证每一次系统升级。
【⚡】 能量过载分发: 执行点赞操作。通过高带宽分发,让优质模组在信息流中高亮显示,赋予知识跨维度的传播力。
【💾】 离线缓存核心: 将本页加入收藏。把这些高频实战逻辑存入你的离线存储器,在遭遇系统崩溃或需要离线检索时,实现瞬时读取。
【💬】 协议加密解密: 在评论区留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞(那些年踩过的坑),通过交互式编译共同绕过技术陷阱。
【🛰️】 信号频率投票: 通过投票发射你的选择。你的每一次点击都在重新定义矩阵的进化方向,决定下一个被全量拆解的技术节点。

