C语言实现堆排序

堆排序属于不稳定排序方法,此外 快速排序和希尔排序也是不稳定算法。

堆是一个完全二叉树

堆排序是时间复杂度为 O(n log n)

堆分为:
①大根堆(既任意根结点 > 左右孩子结点)
②小根堆(既任意根结点 <左右孩子结点)

代码实现:


#include <stdio.h>

// 交换两个整数的值,使用指针作为参数,以便在函数内部修改实际变量的值
// 传入两个整数的指针,将它们所指向的值进行交换
void swap(int* pa1, int* pa2) {
// 临时变量,用于存储 *pa1 的值
int tmp = *pa1;
// 将 *pa2 的值赋给 *pa1
*pa1 = *pa2;
// 将临时变量 tmp(原 *pa1 的值)赋给 *pa2
*pa2 = tmp;
}

// 堆化函数,用于将以索引 i 为根的子树调整为大根堆
// pa 是指向数组的指针,n 是数组的长度,i 是当前要调整的子树的根节点索引
void heapify(int* pa, int n, int i) {
// 初始化 largest 为当前根节点的索引
int largest = i;
// 计算当前根节点的左子节点的索引
int left = i * 2 + 1;
// 计算当前根节点的右子节点的索引
int right = i * 2 + 2;

// 如果左子节点存在且左子节点的值大于当前根节点的值
if (left < n && pa[left] > pa[largest]) {
// 更新 largest 为左子节点的索引
largest = left;
}

// 如果右子节点存在且右子节点的值大于当前根节点的值
if (right < n && pa[right] > pa[largest]) {
// 更新 largest 为右子节点的索引
largest = right;
}

// 如果 largest 不等于 i,说明需要进行交换以满足大根堆的性质
if (largest != i) {
// 交换当前根节点和最大子节点的值
swap(&pa[largest], &pa[i]);
// 递归调用 heapify 函数,继续调整以 largest 为根的子树
heapify(pa, n, largest);
}
}

// 堆排序函数,使用大根堆对数组进行排序
// pa 是指向数组的指针,n 是数组的长度
void heapSort(int* pa, int n) {
// 从最后一个非叶子节点开始,自下而上构建大根堆
for (int i = n / 2 - 1; i >= 0; i--) {
// 调用 heapify 函数调整以 i 为根的子树
heapify(pa, n, i);
}

// 从数组的最后一个元素开始,将堆顶元素(最大值)与当前未排序部分的最后一个元素交换
// 然后对剩余的元素重新调整为大根堆
for (int i = n - 1; i > 0; i--) {
// 交换堆顶元素和当前未排序部分的最后一个元素
swap(&pa[i], &pa[0]);
// 对剩余的 i 个元素重新调整为大根堆
heapify(pa, i, 0);
}
}

// 打印数组元素的函数
// pa 是指向数组的指针,n 是数组的长度
void Print(int* pa, int n) {
// 遍历数组中的每个元素
for (int i = 0; i < n; i++) {
// 打印当前元素,并在元素之间添加制表符分隔
printf("%d\t", pa[i]);
}
// 打印换行符,使输出格式更清晰
printf("\n");
}

int main() {
// 定义一个包含 9 个整数的数组
int arr[9] = { 2, 7, 3, 9, 1, 6, 8, 5, 4 };
// 计算数组的长度
int n = sizeof(arr) / sizeof(arr[0]);
// 调用堆排序函数对数组进行排序
heapSort(arr, n);
// 调用打印函数输出排序后的数组
Print(arr, n);
return 0;
}

 

 

使用软件:DEV-C++


日期:2025-02-06

posted @ 2025-02-06 18:15  freeyang8  阅读(41)  评论(0)    收藏  举报