Cyber骇客的层级霸权——【优化算法】之【排序算法】堆排序

⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///


WARNING \]: DETECTING HIGH ENERGY **🌊 🌉 🌊 心手合一 · 水到渠成** ![分隔符](https://i-blog.csdnimg.cn/direct/60a3de2294e9439abad47378e657b337.gif) |------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | **\>\>\> 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

注意 :我们在进行升序排序 (从小到大)时,通常使用大顶堆 ;进行降序排序时,使用小顶堆


堆排序的核心逻辑

堆排序主要分为两个核心阶段:

  1. 建堆 (Build Heap) :将一个无序数组调整为一个大顶堆 或者小顶堆
    • 升序:建大堆
    • 降序:建小堆
  2. 排序 (Sort)
    建堆和堆删除中都用到了向下调整 ,因此掌握了向下调整,就可以完成堆排序
    • 堆顶元素(最大值)数组末尾元素交换。
    • 将数组长度减 1(排除已排序的末尾元素)。
    • 对剩下的元素重新进行向下调整 ,使其再次满足大顶堆性质。
    • 重复上述过程,直到堆的大小为 1

堆排序 Heap Sort
核心基础
向下调整 Downward Adjustment
注: 建堆和排序的关键通用技术
第一阶段: 建堆 Build Heap
描述
将无序数组调整为堆结构
策略选择
升序排序
--> 建大顶堆 Max-Heap
降序排序
--> 建小顶堆 Min-Heap
第二阶段: 排序循环 Sorting Loop
前提: 已建成大顶堆/小顶堆
循环步骤

  1. 交换 Swap 堆顶最大值 <--> 数组末尾元素
  2. 缩小范围 Reduce Scope 数组有效长度减 1, 排除已排序元素
  3. 恢复堆性 Restore 对剩余元素重新向下调整
    终止条件
    循环直到堆大小 = 1

向下调整的算法

本次代码将综合堆数据结构 来实现

🔗Lucy的空间骇客裂缝:gitee码云的堆

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++;}

  1. child + 1 < php->size:检查右孩子是否存在
  • 如果child+1小于size,说明有右孩子
  1. php->cmp(php->arr[child + 1], php->arr[child]):
  • 调用比较函数比较右孩子和左孩子

  • 这个比较函数决定了是最大堆 还是最小堆

    • 最大堆:返回a > b
    • 最小堆:返回a < b
  • 如果右孩子更"优"(在大顶堆中更大,在小顶堆中更小),则child++指向右孩子

经过这个判断,child指向左右孩子中更"优"的那个


与父节点比较并交换

  1. 比较选出的孩子和父节点

    • 如果孩子更"优"(需要交换)
  2. 交换父节点和孩子节点的值

    • Swap函数交换两个元素
  3. 更新索引,继续向下调整

    • parent = child:父节点下移到刚才交换的位置

    • child = parent * 2 + 1:重新计算新的左孩子索引

    • 继续下一轮循环


堆排序代码实现

本次代码将综合堆数据结构 来实现

🔗Lucy的空间骇客裂缝:gitee码云的堆

注意编写前需要在头文件进行声明!

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]范围内向下调整

🔨关于测试堆排序的分文件代码

🔗Lucy的空间骇客裂缝:gitee码云的堆排序


💻结尾--- 核心连接协议

警告: 🌠🌠正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层,请执行以下指令序列以同步数据:🌠🌠


【📡】 建立深度链接: 关注本终端。在赛博丛林中深耕底层架构,从原始代码到进阶协议,同步见证每一次系统升级。

【⚡】 能量过载分发: 执行点赞操作。通过高带宽分发,让优质模组在信息流中高亮显示,赋予知识跨维度的传播力。

【💾】 离线缓存核心: 将本页加入收藏。把这些高频实战逻辑存入你的离线存储器,在遭遇系统崩溃或需要离线检索时,实现瞬时读取。

【💬】 协议加密解密:评论区留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞(那些年踩过的坑),通过交互式编译共同绕过技术陷阱。

【🛰️】 信号频率投票: 通过投票发射你的选择。你的每一次点击都在重新定义矩阵的进化方向,决定下一个被全量拆解的技术节点。



相关推荐
UP_Continue6 小时前
C++11--引言折叠与完美转发
开发语言·c++
cpp_25016 小时前
P8597 [蓝桥杯 2013 省 B] 翻硬币
数据结构·c++·算法·蓝桥杯·题解
人邮异步社区6 小时前
C++之父的《C++程序设计语言》(第4版)重译出版!
java·jvm·c++
墨有6666 小时前
C++ 模板入门:从函数模板到类模板
c++
前端小L6 小时前
双指针专题(四):像毛毛虫一样伸缩——「长度最小的子数组」
javascript·算法·双指针与滑动窗口
杨云龙UP7 小时前
Windows环境下安装SQL Server 2016企业版+SP3补丁+SSMS连接操作手册_20251230
运维·服务器·数据库·sql·算法·sqlserver·哈希算法
环黄金线HHJX.7 小时前
【拼音字母量子编程语言AiPQL】
开发语言·ide·人工智能·算法·编辑器·量子计算
(❁´◡`❁)Jimmy(❁´◡`❁)7 小时前
Graph and Queries UVA - 1479
算法
浅川.257 小时前
STL专项:vector 变长数组
c++·stl·vector