【排序 - 堆排序】

堆排序(Heap Sort)是一种高效的排序算法,利用了堆这种数据结构的特性。堆排序的时间复杂度为 O(n log n),并且是一个原地排序算法,不需要额外的存储空间。

堆的基本概念

堆是一种特殊的树形数据结构,分为最大堆和最小堆两种类型:

  • 最大堆:父节点的值大于或等于任何一个子节点的值。
  • 最小堆:父节点的值小于或等于任何一个子节点的值。

堆排序利用了最大堆的性质来进行升序排序,具体过程如下:
在这里插入图片描述

堆排序算法步骤

  1. 构建最大堆

    • 将待排序的数组看作是一个完全二叉树,通过调整部分节点的值,使得整个树满足最大堆的性质。
  2. 堆化数组

    • 从数组的中间位置开始,逐步向前调整,使得每个父节点都大于等于其子节点,从而得到一个最大堆。
  3. 排序

    • 将堆顶元素(最大值)与堆的最后一个元素交换位置,然后重新调整堆,除去最后一个元素,再次形成最大堆。重复这个过程,直到整个数组排序完成。

C语言实现

下面是用C语言实现堆排序的代码示例:

#include <stdio.h>

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

// 调整堆,使得以root为根节点的子树满足最大堆的性质
void heapify(int arr[], int n, int root) {
    int largest = root;  // 初始化根节点为最大值
    int left = 2 * root + 1;  // 左子节点
    int right = 2 * root + 2; // 右子节点

    // 如果左子节点大于根节点,则更新最大值的索引
    if (left < n && arr[left] > arr[largest])
        largest = left;

    // 如果右子节点大于当前的最大值,则更新最大值的索引
    if (right < n && arr[right] > arr[largest])
        largest = right;

    // 如果最大值不是根节点,则交换并递归调整堆
    if (largest != root) {
        swap(&arr[root], &arr[largest]);
        heapify(arr, n, largest);
    }
}

// 堆排序函数
void heap_sort(int arr[], int n) {
    // 构建最大堆(从最后一个非叶子节点开始向前调整)
    for (int i = n / 2 - 1; i >= 0; i--)
        heapify(arr, n, i);

    // 从堆顶开始将元素逐个移出堆
    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]);

    printf("排序前:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    heap_sort(arr, n);

    printf("排序后:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

代码解释

  • swap 函数用于交换数组中两个元素的值。
  • heapify 函数用于调整堆,使得以指定根节点为起点的子树满足最大堆的性质。
  • heap_sort 函数首先构建最大堆,然后逐步将堆顶元素(最大值)与堆的末尾元素交换,再重新调整堆,最终完成排序。

时间复杂度

堆排序的时间复杂度为 O(n log n),空间复杂度为 O(1),是一个原地排序算法,适合处理大规模数据的排序问题。

总结

堆排序利用堆这种数据结构的特性,通过构建最大堆和不断调整堆的过程来实现排序。它的时间复杂度稳定在 O(n log n),并且适用于大数据量的排序需求。通过本文,我们深入了解了堆排序的原理和实现方式,并通过C语言代码展示了如何实现堆排序算法。对于理解高效排序算法和算法设计有着重要的帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/789592.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新版FMEA培训未能达到预期效果怎么办?

在制造业的质量管理中&#xff0c;FMEA&#xff08;Failure Mode and Effects Analysis&#xff0c;失效模式与影响分析&#xff09;是一项至关重要的工具&#xff0c;它帮助企业识别和评估产品或过程中潜在的失效模式&#xff0c;以及这些失效模式可能导致的后果。然而&#x…

css 自定义变量 var()

现在新版本的UI框架&#xff0c;基本使用CSS变量 css的一个函数&#xff1a;var()&#xff0c;此函数在有些场景下能优化不少代码量。 var() 介绍 借用下W3C的定义&#xff1a; var() 函数用于插入自定义的属性值&#xff0c;如果一个属性值在多处被使用&#xff0c;该方法就…

为服务器安全保驾护航的“三道防线”!

前言&#xff1a; 随着互联网的发展与普及&#xff0c;服务器安全性的保护变得越来越重要。服务器是企业和个人在网络中存储和处理敏感数据的重要设备&#xff0c;一旦服务器遭到未经授权的访问或攻击&#xff0c;可能导致数据泄露、系统崩溃等严重后果。因此&#xff0c;具备强…

PHP老照片修复文字识别图像去雾一键抠图微信小程序源码

&#x1f50d;解锁复古魅力&#xff0c;微信小程序黑科技大揭秘&#xff01;老照片修复&更多神奇功能等你来试&#xff01; &#x1f4f8; 【老照片修复&#xff0c;时光倒流的美颜术】 你是否珍藏着一堆泛黄的老照片&#xff0c;却因岁月侵蚀而模糊不清&#xff1f;现在…

k8s离线部署芋道源码前端

目录 概述 编译Dockerfile 构建Dockerfilenginx.conf构建 k8s部署前端镜像部署ingress 概述 本篇将对 k8s离线部署芋道源码前端 进行详细的说明&#xff0c;对如何构建 Dockerfile&#xff0c;如何整合 Nginx&#xff0c;如何整合 ingress 进行实践。 相关文章&#xff1a;naco…

科研绘图系列:R语言两组数据散点分布图(scatter plot)

介绍 展示两组数据的散点分布图是一种图形化表示方法,用于显示两个变量之间的关系。在散点图中,每个点代表一个数据点,其x坐标对应于第一组数据的值,y坐标对应于第二组数据的值。以下是散点图可以展示的一些结果: 线性关系:如果两组数据之间存在线性关系,散点图将显示出…

【ARM】MDK-解决Flexnet服务的error:-13.66

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 记录MDK网络版部署服务器error &#xff1a;-13.66的问题解决方案&#xff0c;后续有相关发现持续更新。 2、 问题场景 在客户的服务器上部署Flexnet服务&#xff0c;将license文件检查过后&#xff0c;确认MAC地址…

高频电流探头与柔性电流探头有什么区别

高频电流探头与柔性电流探头在多个方面存在显著的区别&#xff0c;这些区别主要体现在工作原理、测量特性、应用场合以及结构特点上。 工作原理 高频电流探头&#xff1a;主要采用SMT大规模集成电路&#xff0c;结构坚固可靠。利用电磁感应原理&#xff0c;采用磁电传感器进行…

阿里云通义千问开源两款语音基座模型分别是SenseVoice和CosyVoice

阿里巴巴近期发布了开源语音大模型项目FunAudioLLM&#xff0c;该项目包含了两个核心模型&#xff1a;SenseVoice和CosyVoice。可以精准多语言识别并且进行语音克隆。 SenseVoice&#xff1a;精准多语言识别与情感辨识 SenseVoice主要致力于高精度多语言语音识别、情感辨识和…

大型企业如何整合集成全域数据、解决数据孤岛难题?

今天&#xff0c;我们说一下大型企业全域数据的整合集成问题。 通常&#xff0c;中大型企业和集团公司拥有大量多源异构的数据存储资源&#xff0c;如数据仓库、数据湖以及分布于分子公司和混合多云平台的业务系统&#xff0c;通过传统物理集中统一数据资产管理的方式难度高&a…

JavaWeb__XML、http

目录 一 、XML1.1 常见配置文件类型1.1.1 properties配置文件1.1.2 xml配置文件 1.2 DOM4J进行XML解析1.2.1 DOM4J的使用步骤1.2.2 DOM4J的API介绍 二、 HTTP协议2.1 HTTP简介2.2 请求和响应报文2.2.1 报文的格式2.2.2 请求报文2.2.3 响应报文 一 、XML XML是EXtensible Markup…

实用教程:用 Go 的 net/textproto 包优化文本协议处理

实用教程&#xff1a;用 Go 的 net/textproto 包优化文本协议处理 介绍准备工作环境设置Go 基础回顾 基础使用创建连接发送请求接收响应 高级特性处理 MIME 头多行响应的管理错误处理与调试 实战案例实现一个简单的邮件客户端实现一个基于 net/textproto 的命令行工具 最佳实践…

【pytorch22】激活函数与GPU加速

激活函数 ReLu还是还是可能出现梯度弥散&#xff0c;因为x<0的时候&#xff0c;梯度还是可能小于0 leaky relu&#xff0c;在x<0的时候&#xff0c;梯度就不会为0&#xff0c;梯度不会不动 Relu函数在x0处是不连续的 一种更加光滑的曲线是SELU&#xff0c;是两个函数的…

ChatTTS使用

ChatTTS是一款适用于日常对话的生成式语音模型。 克隆仓库 git clone https://github.com/2noise/ChatTTS cd ChatTTS 使用 conda 安装 conda create -n chattts conda activate chattts pip install -r requirements.txt 安装完成后运行 下载模型并运行 python exampl…

移动应用:商城购物类,是最常见的,想出彩或许就差灵犀一指

在移动应用中&#xff0c;商城购物类的非常常见&#xff0c;模式也非常成熟&#xff0c;想要设计的出彩也是有难度的&#xff0c;这次分享一些不同的。

Power BI DAX常用函数使用场景和代码示例

Power BI函数表达式对于没有接触过的朋友可能会有些迷茫&#xff0c;花一点时间了解一下原理在学习一些常用的DAX函数&#xff0c;就可以解决工作中绝大部分问题&#xff0c;函数使用都是共同的。 以下是一些最常用的DAX函数&#xff0c;如聚合&#xff0c;计数&#xff0c;日期…

插入排序算法(C语言版)

直接插入排序 插入排序&#xff08;insert sort&#xff09;是一种简单的排序算法&#xff0c;它的工作原理与手动整理一副牌的过程非常相似。 具体来说&#xff0c;我们在未排序区间选择一个基准元素&#xff0c;将该元素与其左侧已排序区间的元素逐一比较大小&#xff0c;并…

Postman深度解析:打造高效接口测试自动化流程

《Postman深度解析&#xff1a;打造高效接口测试自动化流程》 一、概述与Postman核心优势 1. 接口测试的重要性与挑战 接口测试是确保软件系统各组成部分能够正确交互的关键环节。随着现代软件系统的复杂性增加&#xff0c;接口的数量和类型也在不断增长&#xff0c;这给接口测…

struts2如何防止XSS脚本攻击(XSS防跨站脚本攻击过滤器)

只需要配置一个拦截器即可解决参数内容替换 一、配置web.xml <filter><filter-name>struts-xssFilter</filter-name><filter-class>*.*.filters.XssFilter</filter-class></filter><filter-mapping><filter-name>struts-xss…

代码随想录(day3)有序数组的平方

暴力求解法&#xff1a; 心得&#xff1a;需要确定范围&#xff0c;比如nums.sort()是在for循环之外&#xff0c;根据函数的功能来确定 return返回的是nums&#xff0c;而不是nums[i]因为返回的是整个数组 class Solution(object):def sortedSquares(self, nums):for i in r…