[数据结构 -- 手撕排序算法第一篇] 堆排序,一篇带你搞懂堆排序

news2024/11/27 14:31:01

目录

1、堆的应用 -- 堆排序

1.1 堆排序的思路分析

2、建堆

2.1 向上调整建堆:O(N*logN)

2.1.1 向上调整代码

2.1.2 向上调整建堆代码

2.2 向下调整建堆:O(N)

2.2.1 向下调整代码

2.2.2 向下调整建堆代码

3、堆排序实现代码

4、堆排序测试


1、堆的应用 -- 堆排序

堆是一个完全二叉树,完全二叉树用数组存储数据最优。

堆排序即利用堆的思想来进行排序,总共分为两个步骤:
1、建堆

升序:建大堆

降序:建小堆

2、利用堆删除的思想来进行排序

建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。

1.1 堆排序的思路分析

我们本篇文章使用小堆进行讲解,小堆排序是降序。

对堆还不是很了解的同学可以浅看一下堆的那篇文章:戳这里即可跳转

1、我们先对数组里的元素进行向下调整建成小堆;

2、小堆的堆顶元素肯定是数组中最小的,因此我们将堆顶元素(数组首元素)与数组尾元素交换,将数组尾元素不在看作是数组中的元素(size--),再从堆顶开始向下调整重新构建小堆,不断重复就可以实现降序排序(升序只要将小堆改为大堆就可以实现)。

2、建堆

我们建堆可以使用向上调整建堆,也可以使用向下调整建堆,我们该如何选择呢?

那肯定是谁的时间复杂度小我就选谁,那接下来我们分析一下两种建堆的时间复杂度:

2.1 向上调整建堆:O(N*logN)

2.1.1 向上调整代码

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])//这里控制大小堆
		{
			Swap(&a[child], &a[parent]);

			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

2.1.2 向上调整建堆代码

//建堆 -- 向上调整,时间复杂度:O(N*log(N))
for (int i = 0; i < size; i++)
{
	AdjustUp(a, i);
}

我们画图来分析一下向上调整建堆时间复杂度:

堆是一个完全二叉树,满二叉树也是完全二叉树,因此我们以满二叉树为例推出向上调整建堆的时间复杂度为O(N*logN)。

2.2 向下调整建堆:O(N)

2.2.1 向下调整代码

void AdjustDown(HPDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)//当child大于了数组大小就跳出循环
	{
		//找出左右孩子中小/大的那个(假设法)
		if (child + 1 < size && a[child + 1] < a[child])
		{
			child++;
		}

		if (a[child] < a[parent])
		{
			Swap(&a[parent], &a[child]);

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

2.2.2 向下调整建堆代码

for (int i = (size - 1 - 1) / 2; i >= 0; i--)
{
    AdjustDown(a, size, i);
}

我们画图来分析一下向下调整建堆时间复杂度:

向下调整建堆时间复杂度:O(N)。

如此分析下来我们就可以知道,向下调正建堆才是最优选择。

3、堆排序实现代码

//堆排序时间复杂度O(N + N*logN)
void HeapSort(int* a, int size)
{
	//升序 -- 建大堆
	//降序 -- 建小堆

	//建堆 -- 向上调整,时间复杂度:O(N*log(N))
	//for (int i = 0; i < size; i++)
	//{
	//	AdjustUp(a, i);
	//}

	//建堆 -- 向下调整,时间复杂度:O(N)
	//倒着调整
	//叶子节点不需要处理
	//倒数第一个非叶子节点:最后一个节点的父亲开始调整
	for (int i = (size - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, size, i);
	}

	//O(N*log(N))
	int end = size - 1;
	while (end)
	{
		//1.先交换
		Swap(&a[0], &a[end]);
		//2.再调整,选出当前大小的数组中最小数
		AdjustDown(a, end, 0);

		end--;
	}
}

4、堆排序测试

我们建的是小堆,因此最终排的是降序。

*** 本篇结束 ***

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文读懂Serverless,它到底有啥用?

各位ICT的小伙伴好呀。 Serverless是最近大家讨论很多的一个话题。 今天我们就来聊聊什么是Serverless&#xff1f; ▉ Serverless是个啥&#xff1f; Server&#xff1a;服务器&#xff0c;Serverless解决问题的产品。 less&#xff1a;更少&#xff0c;Serverless解决问题…

如何解决空指针异常

NPE异常相信 Java 程序员都很熟悉&#xff0c;是 NullPointerException 的缩写&#xff1b;最近业务需求开发的有点着急&#xff0c;测试环境就时不时的来个NPE异常&#xff0c;特别的头疼&#xff1b;作为出镜率最高的异常之一&#xff0c;一旦入行Java开发&#xff0c;可以说…

微服务网关、SpringBoot、Nginx、tomcat8配置跨域

微服务网关、SpringBoot、Nginx、tomcat8配置跨域 跨域是什么?为什么会跨域解决跨域微服务网关处理跨域springboot项目配置跨域nginx配置跨域tomcat8配置跨域 跨域是什么? 跨域是A端向B端发送请求&#xff0c;A端与B端的地址协议、域名、端口三者之间任意一个不同&#xff0c…

Tomcat的优化

Tomcat的优化 一、Tomcat 优化Tomcat 配置文件参数优化 二、系统内核优化三、Tomcat 配置 JVM 参数&#xff1a;参数含义 一、Tomcat 优化 Tomcat默认安装下的缺省配置并不适合生产环境&#xff0c;它可能会频繁出现假死现象需要重启&#xff0c;只有通过不断压测优化才能让它…

吴恩达联手OpenAI的免费课程笔记—面向开发人员的 ChatGPT 提示工程

目录 前言一、大语言模型介绍二、提示指南2-0、导入API key和相关的python库2-1、写清楚的、具体的提示2-1-1、使用分隔符清楚的指示输入的不同部分2-1-2、要求结构化的输出2-1-3、按照指定的条件输出2-1-4、少样本学习 2-2、给模型时间去思考2-2-1、指定完成任务所需要的具体步…

软件外包开发UI管理工具

软件在开发前需要设计UI界面&#xff0c;UI界面是产品经理和开发人员、测试人员之间的交流工具&#xff0c;因此项目中会有多人的工作涉及到的UI界面&#xff0c;这就需要有个好的工具协调相互之间的工作。今天和大家分享一些常用到的工具&#xff0c;希望对大家的工作有所帮助…

插件框架PF4J-从理论到实践

PF4J:Plugin Framework for Java 目录 是什么&#xff1f; 不是什么&#xff1f; 特点 组件 主要类 流程概述 spring-pf4j 思考 功能模块化 我对pf4j的封装和使用demo GitHub - chlInGithub/pf4jDemo: pf4j demo 是什么&#xff1f; 开源轻量级的插件框架。通过插件…

三相三线、三相四线、三相五线制区别

三相三线、三相四线、三相五线制区别 1、三相三线2、三相四线3、三相五线4、三相三线和三相四线的区别5、三相四线和三相五线的区别 1、三相三线 由A、B、C这3根相线俗称火线组成&#xff0c;没有布置零线N和接地线PE&#xff0c;这种布线方式常见于交流380V的上一级10KV的系统…

Maven安装教程

maven环境配置&#xff08;点击此电脑右键属性&#xff09;&#xff1a; 点击高级系统设置&#xff0c;点击环境变量&#xff1a; 开始配置环境变量&#xff08;点击系统变量&#xff0c;新建按钮&#xff09;&#xff1a; 新建系统变量&#xff1a;MAVEN_HOMED:\maven\apac…

vueX学习看这篇就够了

vuex就是为了实现全局状态管理 vuex有哪些东西&#xff1f; state【状态】getter【可以认为是 store 的计算属性&#xff0c;不会修改状态】mutation【唯一修改state的方法&#xff0c;不支持异步】action【不能直接修改state,通过触发mutation修改状态&#xff0c;支持异步】…

GPT聊天功能,逐字返回数据

目录 前言一、前端二、后端1.接收前端请求的api如下是继续向其他接口请求的api如下是直接返回前端数据的api甚至可以返回图片 2.模拟GPT的接口 前言 我们在和GPT交流的时候发现GPT总是逐字的显示&#xff0c;因为GPT是一种基于神经网络的自然语言处理模型&#xff0c;它的训练…

王道考研计算机网络第一章知识点汇总

以上内容为1.1概念与功能的重点知识点 以下为1.2组成与分类&#xff1a; P2P模式下每台主机既可以是客户也可以是服务器&#xff0c;主机越多资源分享速度越快。 1.3标准化工作及相关组织 1.4性能指标 带宽只是指的是从主机内部往传输链路上投送数据的最大能力(从入口端放入数…

棱镜七彩中标浦发银行项目 助力金融行业开源治理

近日&#xff0c;棱镜七彩凭借出色的研发实力和优秀的产品服务能力在众多竞标企业中脱颖而出&#xff0c;成功中标上海浦东发展银行创新实验室“开源治理扫描工具信创改造课题”项目。棱镜七彩将为浦发银行在开源软件治理、软件安全可靠性等方面提供全方位支持。 在数字经济发…

odoo from 表单自定义按钮 执行JS代码 并调用websoket

业务场景&#xff1a; 集成串口读取RFID数据。由于串口是需要在客户端本地电脑执行才可以拿到数据 但是系统 部署在服务器 不能直接调用串口。 解决方案&#xff1a; 利用websoket通信 调用串口 传输 读取到的串口数据&#xff0c;解决服务器与本地之间的通信 本场景是基于odo…

深度解析:2023年软件测试的10个新趋势和挑战

随着技术的飞速发展&#xff0c;软件测试的角色和责任也在经历重大转变。我们在2023年目前所面临的一些新趋势和挑战值得所有从业人员关注。以下是这些主要趋势和挑战的深度分析。 趋势一&#xff1a;人工智能和机器学习在测试中的应用 AI和ML正在越来越多地应用于软件测试&am…

给httprunnermanager接口自动化测试平台演示参数化(五)

文章目录 一、背景1.1、前情回顾 二、参数化实现三、总结 一、背景 参数化&#xff0c;在使用httprunner框架的时候&#xff0c;参数话说实在的不是很实用&#xff0c;因为更多是场景化的用例编写&#xff0c;不用过多的去参数化批量执行&#xff0c;无非也就是登录注册查询啥的…

数据库系统概论 ---知识点大全(期末复习版)

&#xff08;一&#xff09;绪论 数据(Data)&#xff1a;是数据库中存储的基本对象 数据的定义&#xff1a;描述事物的符号记录 数据的种类&#xff1a;文字、图形、图象、声音等 数据的特点&#xff1a;数据与其语义是不可分的 数据库(Database,简称DB)&#xff1a;是长期…

数据结构与算法-跳表详解

我们知道如果一个数组是有序的&#xff0c;查询的时候可以使用二分法进行查询&#xff0c;时间复杂度可以降到 O(logn) &#xff0c;但如果链表是有序的&#xff0c;我们仍然是从前往后一个个查找&#xff0c;这样显然很慢&#xff0c;这个时候我们可以使用跳表&#xff08;Ski…

chatgpt赋能python:Python如何依次取字符——一种简单有效的方法

Python如何依次取字符——一种简单有效的方法 1. 介绍 Python 常常被用于编写文本处理脚本&#xff0c;而文本处理中的一个常见任务就是依次取字符。本文将介绍一种简单高效的方法&#xff0c;让您可以在 Python 中便捷地完成此操作。 2. 如何依次取字符 Python 中的字符串…

黑客入门必备指南

在探讨黑客如何入门之前&#xff0c;首先我们的思想要端正。 作为一名黑客&#xff0c;必须要有正直善良的价值观。 或许你听过这么一句话“能力越大&#xff0c;责任越大”作为一名黑客就是如此&#xff0c;黑客的技术越精湛&#xff0c;能力就越大&#xff0c;就越不能去干…