[西门子] 你可能不知道的C语言排序神器:以实例来完美诠释!

[复制链接]
查看212 | 回复0 | 2024-6-28 08:00:08 | 显示全部楼层 |阅读模式
>

上节课讲了关于C语言堆排序的介绍,本节来说一说关于堆排序如何应用,举出一个详细的例子来实践!
你可能不知道的C语言排序神器:堆排序




概念回顾:
堆排序是一种基于堆这种数据结构的排序算法,它的时间复杂度为


空间复杂度为

是一种原地排序和不稳定排序的算法。堆排序的一个典型的应用场景是优先队列,它可以用于实现高效的任务调度等问题。堆排序的实现需要用到指针,指针是一种存储地址的变量,它可以用来访问和修改数组中的元素。




堆排序的应用案例

堆排序的一个典型的应用场景是优先队列。优先队列是一种特殊的队列,它的每个元素都有一个优先级,出队的时候总是按照优先级从高到低的顺序出队。优先队列可以用堆来实现,具体的做法是:
入队:把新元素放到堆的末尾,然后向上调整堆的结构,使其满足堆的性质。
出队:把堆顶元素和堆尾元素交换,然后缩小堆的大小,再向下调整堆的结构,使其满足堆的性质,最后返回堆顶元素。
优先队列的一个应用例子是任务调度。假设有一些任务需要在一台计算机上执行,每个任务都有一个优先级和一个执行时间,计算机每次只能执行一个任务,而且不能中断正在执行的任务。我们希望按照优先级从高到低的顺序执行任务,以尽快完成所有的任务。这个问题可以用优先队列来解决,具体的做法是:
1、把所有的任务放入一个大顶堆中,以优先级作为排序的依据。
2、每次从堆中取出优先级最高的任务,执行该任务,然后从堆中删除该任务。
3、重复上述步骤,直到堆为空。
这样,我们就可以保证每次执行的任务都是优先级最高的,从而达到最优的任务调度效果


程序





















































































#include <stdio.h>#include <stdlib.h>
// 定义一个交换函数,用于交换两个整数的值void swap(int *a, int *b) {    int temp = *a;    *a = *b;    *b = temp;}// 定义一个调整函数,用于将一个数组调整为一个大顶堆void adjust(int *arr, int len, int index) {    // 计算左右子节点的索引    int left = 2 * index + 1;    int right = 2 * index + 2;    // 初始化最大值的索引为当前节点的索引    int max = index;    // 如果左子节点存在,并且左子节点的值大于当前节点的值,更新最大值的索引为左子节点的索引    if (left < len && arr[left] > arr[max])   {        max = left;    }    // 如果右子节点存在,并且右子节点的值大于当前节点的值,更新最大值的索引为右子节点的索引    if (right < len && arr[right] > arr[max])   {        max = right;    }    // 如果最大值的索引不等于当前节点的索引,说明当前节点不满足大顶堆的性质,需要交换当前节点和最大值节点的值,并对最大值节点进行递归调整    if (max != index)   {        swap(&arr[max], &arr[index]);        adjust(arr, len, max);    }}// 定义一个堆排序函数,用于对一个数组进行升序排列void heapSort(int *arr, int len) {    // 从最后一个非叶子节点开始,从右到左,从下到上,对每个节点进行调整,使整个数组成为一个大顶堆    for (int i = len / 2 - 1; i >= 0; i--)   {        adjust(arr, len, i);    }    // 从最后一个元素开始,将堆顶的元素(最大值)与堆尾的元素交换,然后缩小堆的大小,对堆顶的元素进行调整,重复这个过程,直到堆的大小为1    for (int j = len - 1; j > 0; j--)   {        swap(&arr[0], &arr[j]);        adjust(arr, j, 0);    }}// 定义一个打印函数,用于打印一个数组的元素void printArray(int *arr, int len) {    printf("[");    for (int i = 0; i < len; i++)   {        printf("%d", arr);        if (i < len - 1)     {            printf(", ");        }    }    printf("]\n");}
// 定义一个主函数,用于测试int main() {    // 创建一个测试用的数组    int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};    // 获取数组的长度    int len = sizeof(arr) / sizeof(arr[0]);    // 打印原始数组    printf("原始数组是:\n");    printArray(arr, len);    // 调用堆排序函数,对数组进行升序排列    heapSort(arr, len);    // 打印排序后的数组    printf("排序后的数组是:\n");    printArray(arr, len);    // 返回0,表示程序正常结束    return 0;}



运行调试
运行VC6.0,输入原始数组:【9,8,7,6,5,4,3,2,1】

经过堆排序运算结果:【1,2,3,4,5,6,7,8,9】






堆排序的缺点是:

  • 它是一种不稳定的排序算法,即相同的元素在排序后可能会改变原来的相对顺序;
  • 它的数据交换次数较多,会影响缓存的命中率,降低排序的性能;
堆排序适用于以下的场景:

  • 数据量较大,且需要频繁地找出最大值或最小值的问题,比如优先队列、任务调度、中位数、前K大等;
  • 数据量较小,且对稳定性要求不高的问题,比如一些简单的排序问题;
堆排序不适用于以下的场景:

  • 数据量较大,且对稳定性要求高的问题,比如一些涉及到人员信息或者业务逻辑的排序问题;
  • 数据量较小,且对时间效率要求高的问题,比如一些实时性较强的排序问题;



觉得有用的话可以转发给你身边需要的朋友!非常感谢!!!






点赞加关注,学习不迷路
微信公众号|工控小新
EPLAN电气绘图、TIA博图基础 、CAD、C语言教学、单片机基础、三菱PLC ... 每日持续更新中




发现“分享”“赞”了吗,戳我看看吧


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则