八大排序算法-堆排序

2023-11-05

在说堆排序之前,要先说明二叉堆的概念。因为堆排序就是通过二叉堆来实现的。

注:以下说会用堆来作二叉堆的简称。至于堆的定义,大家可以自行查阅。

在了解完堆之后,我们知道堆有大根堆和小根堆的不同。我们先了解堆排序的思想,之后用一个大根堆来实现代码。

堆排序的定义是:利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征(这里我们用大根堆),调整数组的存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n - 1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列,在当前无序区中选取最大(或最小)关键字的记录变得简单。

堆排序的基本思想:

简单一点就是堆排序就是不断的选出最小的值,然后放到有序区的排序方法。所以堆排序是选择排序的一种
既然堆排序用到了堆,那我们就必须要把排序的数组转化成堆的格式才能用得到堆的性质。
所以,我们有两个步骤要做:
一、建堆:建堆是不断调整堆的过程,从len/2处开始调用②,把从第len/2个结点为根的子树开始,该子树成为堆,之后向前依次对各结点为根的子树进行调整,使之成为堆,至根结点。该过程是线性的,时间复杂度为:O(n)。

二、调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大者,如果最大值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lg(n)的操作,因为是沿着深度方向进行调整的。

三、堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。

堆排序过程的时间复杂度是O(nlgn)。

因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)。

算法:

//array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
//本函数功能是:根据数组array构建大根堆
void HeapAdjust(int array[], int i, int nLength)
{
	int nChild;
	int nTemp;
	for (; 2 * i + 1<nLength; i = nChild)
	{
		//子结点的位置=2*(父结点位置)+1
		nChild = 2 * i + 1;
		//得到子结点中较大的结点
		if (nChild<nLength - 1 && array[nChild + 1]>array[nChild])
			++nChild;
		//如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
		if (array[i]<array[nChild])
		{
			nTemp = array[i];
			array[i] = array[nChild];
			array[nChild] = nTemp;
		}
		else break; //否则退出循环
	}
}
//堆排序算法
void HeapSort(int array[], int length)
{
	int i;
	//调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
	//length/2-1是最后一个非叶节点,此处"/"为整除
	for (i = length / 2 - 1; i >= 0; --i)
		HeapAdjust(array, i, length);
	//从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
	for (i = length - 1; i > 0; --i)
	{
		//把第一个元素和当前的最后一个元素交换,
		//保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
		array[i] = array[0] ^ array[i];
		array[0] = array[0] ^ array[i];
		array[i] = array[0] ^ array[i];

		//不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
		HeapAdjust(array, 0, i);
	}
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

八大排序算法-堆排序 的相关文章

  • 静态只读字符串数组

    我在我的 Web 应用程序中使用静态只读字符串数组 基本上数组有错误代码 我将所有类似的错误代码保存在一个数组中并检查该数组 而不是检查不同常量字符串中的每个错误代码 like public static readonly string m
  • 为什么在连接两个字符串时 Python 比 C 更快?

    目前我想比较 Python 和 C 用来处理字符串的速度 我认为 C 应该比 Python 提供更好的性能 然而 我得到了完全相反的结果 这是 C 程序 include
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 以编程方式读取 SQL Server 查询计划建议的 SQL 特定执行的索引?

    如果我在 SSMS 中运行此命令 set showplan xml on GO exec some procedure arg1 arg2 arg3 GO set showplan xml off GO 我获得查询执行中涉及的完整调用堆栈的
  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 为什么从字典中获取时会得到 Action<> 的克隆?

    我有以下字典 private Dictionary
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • String.Empty 与 "" [重复]

    这个问题在这里已经有答案了 可能的重复 String Empty 和 有什么区别 https stackoverflow com questions 151472 what is the difference between string
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone

随机推荐

  • Fiddler手机抓包

    本文转载自 Fiddler手机抓包 机智的老猫咪 博客园 Fiddler是一款安装在PC上的抓包软件 它不仅可以对pc上的程序进行抓包 也可以对手机上的程序进行抓包 下面说下抓取手机程序的步骤 一 PC端设置 1 PC上Fiddler抓取H
  • 【放苹果】m个苹果放到n个盘子中

    m个相同的苹果 放在n个相同的盘子中 由于相同 使用排列组合的方法不好处理 这里选用递归调用的方式解决问题 8个苹果 放在3个盘子里 8个苹果 放在2个盘子 5个苹果 放在2个盘子 每盘已经放入1个苹果 2个苹果 放在2个盘子里 每盘已经放
  • 设置linux防火墙的的脚本,Linux开启防火墙并设置策略脚本

    bash bash 现有规则全部注销 iptables P INPUT ACCEPT iptables F 全部进入端口禁止 iptables P INPUT DROP 开启ping和snmp iptables A INPUT i lo j
  • uniapp封装promise接口

    uniapp封装promise接口 uni app题拱了uni requet 方法 发起网络请求 首先在根目录里创建一个request文件夹 在里面创建request js文件 在文件里编写发起网络请求的代码 在全局main js中配置 在
  • vue项目使用vue-quill-editor,光标位置控制(已解决)

    查了网上很多资料使用 都没有解决 故记录在此 全局引入 import Vue from vue import VueQuillEditor from vue quill editor require styles import quill
  • [重点]call、apply和bind的区别以及源码解析

    前言 在前端面试中 最常见的面试题 this的指向问题 如何改变this指向 call apply和bind的区别以及源码解析 如果面试官问到this的指向问题 那么你去引导面试官 让他问你如何改变this指向 call apply和bin
  • Wazuh检测反弹shell

    Wazuh通过在agent服务器上执行指定的命令 并收集命令结果 可以在一定程度上发现反弹shell的入侵行为 目前有2中常见的检测方法 一种是通过netstat输出网络连接中的shell进程来识别 另一种是通过ps输出进程信息中的反弹sh
  • 光纤中的多种光学模式芯径_「涨知识」你想知道的光纤常识都在这里了,看不看随你...

    光纤已经成为远距离有线信号传输的主要手段 安装 维护光纤也是弱电人的基本功 光纤中涉及的理论知识 组件和铺设要点都很多 我们在这里作了一些梳理 三种光 不是所有的光都能用于光纤中信号传播 光线中主要使用三种波长的光 850 nm 1300
  • Zotero文献导入到Endnote

    1 2 导入的时候 请选择
  • STM32 DAC + DMA + TIM 输出正弦波,三角波,方波信号

    硬件平台 STM32F4 库类型 标准库 参考 二代示波器教程 第12章 示波器设计 DAC信号发生器的实现 DAC框图如下 通过TIM触发DAC转换 转换完成后通过DMA输出 DMA通道框图 DAC输出阻抗的问题 DAC集成了2个输出缓存
  • matlab练习程序(弧形、圆柱投影的复原)

    前一段介绍了从矩形图像到圆柱的正向投影 看这里和这里 今天介绍如何从已经投影的图像反映射到原图像上 本来此种变换一定是需要数学公式的 不过这里只是用了一个很简单的方式来完成反映射 具体就把每一列有像素数据的长度拉伸到原图像的高就行了 原图像
  • html网页超链接

    HTML网页超链接可以通过a标签来添加超链接 其语法是 a href target self title a 它的两个属性值分别是href用来设置网页目标地址 target是用来设置打开超链接的方式 a href 网址 链接地址 targe
  • 字体子集化fontmin应用

    const fm require fontmin const f 字体名称 ttf const fontmin new fm fontmin src f use fm glyph text 天地玄黄 宇宙洪荒 use fm ttf2svg
  • 二、图像二值化方法(python)---阈值全局固定、大津法

    文章目录 阈值全局固定 利用python实现阈值全局固定时的二值化 效果图 大津法OTSU 利用Python实现大津法 效果图如下 图像二值化也叫做图像阈值化处理 通过设定某个阈值为门限 把多灰度级的图像转化为仅仅有两个极端的灰度级 0和2
  • C/C++编程笔记:如何将字符串转换为数字,数字转换为字符串?

    通常 或更具体地说 在竞争性编程中 有许多情况需要将数字转换为字符串或将字符串转换为数字 但是缺乏某些必不可少的工具的知识使我们不得不这样做 本文介绍了一些实现此任务的方法 将字符串转换为数字 方法1 使用stringstream类或ssc
  • 【转】探索推荐引擎内部的秘密

    from http www ibm com developerworks cn web 1103 zhaoct recommstudy1 index html ca drs 赵 晨婷 软件工程师 IBM 马 春娥 软件工程师 IBM 简介
  • 基于API调用管理的SDN应用层DDoS攻击防御机制

    摘要 软件定义网络 SDN software defined network 针对北向接口安全研究少 加之缺乏严格的访问控制 身份认证及异常调用检测等机制 导致攻击者有机会开发恶意的应用程序 造成北向应用程序接口 API applicati
  • Ubuntu中最简单好用截图工具shutter安装

    题记 在ubuntu中 shutter截图工具是我目前使用过最简单好用的截图神器 安装 直接在ubuntu软件市场中搜索下载 然后安装即可了
  • 软件测试工程师必备的10个测试技术体系(零基础入行测试必学)

    很多测试新手在刚开始学习软件测试的时候都不知道该如何开始 以及软件测试需要掌握哪些必备的知识点 以下是根据个人总结 粗略整理的一份软件测试学习大纲 基本涵盖了软件测试工程师需要掌握的全部技能 希望给准备学习测试的朋友提供一点指引和帮助 PS
  • 八大排序算法-堆排序

    在说堆排序之前 要先说明二叉堆的概念 因为堆排序就是通过二叉堆来实现的 注 以下说会用堆来作二叉堆的简称 至于堆的定义 大家可以自行查阅 在了解完堆之后 我们知道堆有大根堆和小根堆的不同 我们先了解堆排序的思想 之后用一个大根堆来实现代码