C语言---排序算法9---堆排序法

文章目录

算法原理

堆排序是一种基于二叉堆数据结构的比较排序算法。

该算法利用了堆的特性,不了解堆的特性可以去了解先。

其核心分为两步:

1、构建最大堆:将无序数组构造成最大堆(父节点值 ≥ 子节点值)

2、排序阶段:重复将堆顶最大值交换到数组末尾,并调整剩余元素维持堆性质

白话总结起来以下几个步骤:

1、将当前数组构建为最大堆或者最小堆,目的是为了将最大值或最小值放置在堆顶,就是一个找出最大值或最小值的过程。

2、将堆顶值与数组末尾交换,交换完成后已经将一个最大值最小值放置在数组末端,缩小建堆的大小,重复步骤1,目的是为了将步骤1中找到的最大值或最小值放置提取出来,并且不在处于到最大值或最小值的查找过程中。

注意点:在完成一次建堆之后的建堆,不需要从最后一个非叶子节点开始,因为除了被交换的堆顶外,下面的两个子树都是符合要求的堆。

循环完成步骤1和步骤2,即可完成排序过程。

C语言实现代码

bash 复制代码
#include <stdio.h>

// 交换两个整数的值
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 维护最大堆性质(核心操作)
// i为构建的节点,n为整个堆的大小
void heapify(int arr[], int n, int i) {
    int largest = i;       // 初始化最大元素为当前节点
    int left = 2*i + 1;    // 左子节点索引
    int right = 2*i + 2;   // 右子节点索引

    // 若左子节点存在且大于当前最大值
    if (left < n && arr[left] > arr[largest])
        largest = left;

    // 若右子节点存在且大于当前最大值
    if (right < n && arr[right] > arr[largest])
        largest = right;

    // 如果最大值不是当前节点,交换并递归调整
    if (largest != i) {
        swap(&arr[i], &arr[largest]);
        heapify(arr, n, largest); // 递归调整受影响的子堆
    }
}

// 堆排序主函数
void heapSort(int arr[], int n) {
    // 步骤1:构建最大堆(从最后一个非叶子节点开始),即数组中最后一个数的父节点。
    // 从非叶子节点开始是因为没有子节点的节点本身就是符合要求的堆
    for (int i = n/2 - 1; i >= 0; i--)
        heapify(arr, n, i);

    // 步骤2:逐个提取最大值
    for (int i = n-1; i > 0; i--) {
        swap(&arr[0], &arr[i]);  // 将堆顶(最大值)移到末尾
        heapify(arr, i, 0);      // 调整剩余元素的堆
    }
}

// 测试代码
int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int n = sizeof(arr)/sizeof(arr[0]);

    heapSort(arr, n);
    printf("排序结果:");
    for (int i=0; i < n; i++)
        printf("%d ", arr[i]);
    return 0;
}

优化点

1、可改用迭代实现heapify减少递归开销。

2、对小型数组可改用插入排序优化。

3、支持最小堆实现降序排序。

4、可扩展为优先队列数据结构。

参考视频

4分钟学堆排序(手机动画版)
数据结构合集 - 堆与堆排序(算法过程, 效率分析, 稳定性分析)

相关推荐
Tisfy2 分钟前
LeetCode 0301.删除无效的括号:二进制枚举 / 回溯
算法·leetcode·字符串·题解·回溯·括号匹配·二进制枚举
Nil20810 分钟前
leetcode 322零钱兑换
算法·leetcode·职场和发展
老王爱玩车14 分钟前
动态内存管理
c语言·开发语言·学习·面试
海绵宝宝转agent14 分钟前
2026-10-9 leetcode100刷题+面经整理
笔记·算法·面试
yi01125 分钟前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针
木井巳26 分钟前
【BFS 解决拓扑排序】课程表
java·算法·leetcode·广度优先·宽度优先·推荐算法·图搜索算法
Logic10139 分钟前
C语言/数据结构数位DP题解:平滑排列数字统计——区间内相邻位差不超过K的数字个数
c语言·数据结构·动态规划·时间复杂度·数位dp·算法题·前导零处理
扶风ff1 小时前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
yi0111 小时前
LeetCode 15:三数之和|排序 + 双指针,如何避免重复答案?
笔记·python·算法·leetcode·双指针
Zwawa1 小时前
把 AO 接回来:黑线和白底之间到底差了多少
c语言·单片机·嵌入式