堆排序算法

news2025/7/23 8:14:11

一、大顶堆和小顶堆概念

        堆排序是利用堆数据结构而设计的一种排序算法,堆排序是一种选择排序,其最坏,最好,平均时间复杂度均为O(nlogn),同时也是不稳定排序
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆, 如下图所示,其中大顶堆的性质:arr[i] >= arr[2i] && arr[i] >= arr[2i+1]

 

每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆,如下图所示,其中小顶堆性质:arr[i] <= arr[2i] && arr[i] <= arr[2i+1]

二、堆排序的基本思想

(1)将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
(2)将堆顶元素与末尾元素交换,将最大元素放到数组末端;
(3)重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整和           交换步骤,直到整个序列有序。 

举例:

1、将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
(1)假设给定无序序列结构如下:

  

 2、此时从数组的一半处开始进行调整(数组的0号位不存数,因此数组实际长度要减1),即从2号位开始调整。

(1)让root指向2号结点,让child=2*root即指向4号结点;

(2)判断child + 1 <= length && list->data[child] < list->data[child + 1],即取左右孩子结点中的较大的一个;

(3)若满足条件则右孩子结点的值大,取右孩子(child++);否则取左孩子(child);因为1<4,所有取右孩子(child=5)

(4)找到左右孩子结点的较大者后与其父节点(root=2)进行比较,若child所指结点的值大于root所指结点的值则需要将两个结点的值进行互换,否则不需要进行值的互换;因为list->data[root] >= list->data[child],所以不需要进行值的互换

(5)让root=child,若2*root<=length,则在进行上述操作进行调整;否则进行下一个结点的调整即3

(6)将2号位调整完成后,堆的形状和数组中的内容如下图所示

3、从1号结点开始调整

(1)root指向1号结点,child=2*root指向2号结点

(2)判断child + 1 <= length && list->data[child] < list->data[child + 1],即取左右孩子结点中的较大的一个;

(3)若满足条件则右孩子结点的值大,取右孩子(child++);否则取左孩子(child);因为5>2,所有取左孩子(child=2)

(4)找到左右孩子结点的较大者后与其父节点(root=1)进行比较,若child所指结点的值大于root所指结点的值则需要将两个结点的值进行互换,否则不需要进行值的互换;因为list->data[root] <= list->data[child],所以需要进行值的互换

(5)让root=child,若2*root<=length,则在进行上述操作进行调整;否则进行下一个结点的调整,

(6)经过该轮调整后结果如下图所示

 4、将第一个结点与最后一个结点值进行互换

 5、再从length-1个长度重复以上操作,继续进行调整,交换,如此反复进行,最终使得整个序列有序

三、代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>

#define MAXSIZE 20
typedef int DATATYPE;

typedef struct seqList
{
	DATATYPE data[MAXSIZE];
	int length;
}SeqList;
//初始化顺序表
void InitSeqList(SeqList* list)
{
	for (int i = 0; i < MAXSIZE; i++)
	{
		list->data[i] = 0;
	}
	list->length = 0;
}
//创建顺序表
void CreateSeqList(SeqList* list)
{
	DATATYPE data, length;
	printf("请输入要创建的顺序表的长度:");
	scanf_s("%d", &length);
	printf("请输入数据:");
	for (int i = 1; i <= length; i++)
	{
		scanf_s("%d", &data);
		list->data[i] = data;
		list->length++;
	}
}
//堆排序调整过程
void AdjustHeap(SeqList* list, int root, int length)//root表示要开始调整的结点
{
	list->data[0] = list->data[root];//先保存要调整结点
	int child = 0, temp = 0;
	for (;2 * root <= length;root = child)
	{
		child = 2 * root;//左孩子
		if (child + 1 <= length && list->data[child] < list->data[child + 1])//取左右孩子中较大一个
			child++;
		if (list->data[0] >= list->data[child])//若已经是大顶堆不需要调整
			break;
		else
		{
			list->data[root] = list->data[child];//调整堆使根节点为最大的
			list->data[child] = list->data[0];
		}
	}
}
void swap(int* a, int* b)
{
	int temp = 0;
	temp = *a;
	*a = *b;
	*b = temp;
}
//堆排序
void HeapSort(SeqList* list, int length)
{
	int i, j;
	for (i = length / 2; i >= 1; i--)//从一半结点处开始调整堆
	{
		AdjustHeap(list, i, length);
	}
	for (j = length; j >= 1; j--)
	{
		swap(&list->data[j], &list->data[1]);//将堆顶元素与最后一个元素互换
		AdjustHeap(list, 1, j - 1);//在调整
	}
}

//打印
void PrintfSeqList(SeqList* list)
{
	for (int i = 1; i <= list->length; i++)
	{
		printf("%6d", list->data[i]);
	}
	printf("\n");
}
int main(void)
{
	SeqList list;
	

	//堆排序
	printf("--------------------堆排序--------------------\n");
	InitSeqList(&list);
	CreateSeqList(&list);
	PrintfSeqList(&list);
	HeapSort(&list,list.length);
	printf("堆排序得到的排序序列为:");
	PrintfSeqList(&list);
	

	system("pause");
	return EXIT_SUCCESS;
}

 

 

 

 

 

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

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

相关文章

Hive数据定义语言-DDL-建表高阶语法(内外部、分区、分桶、事务、视图、物化视图)

文章目录1. 内部表、外部表1.1 内部表1.2 外部表1.3 内、外部表差异1.4 Location关键字的作用2. 分区表-Partitioned Tables2.1 概念2.2 创建2.3 分区表数据加载2.3.1 静态分区2.3.2 动态分区2.4 注意事项3. 分桶表-Bucketed Tables3.1 概念3.2 规则3.3 语法3. 事务表-Transact…

编译openMVG出现的错误的解决

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> submodule(s) are missing, please update your repository 在使用CMake生成openMVG解决方案时&#xff0c;出现错误&#xff1a; CMake Error at CMakeL…

另眼看数据中台

目录 前言&#xff1a; 一、故事的开始 二、成也中台&#xff0c;败也中台 1、中台是什么 2、数据中台与企业数字化转型 3、中台的赋能 4、数据中台、业务中台、技术中台 5、中台不一定适合你 ​编辑​编辑小结&#xff1a; 三、 自检数据应用的成熟度 前言&#xff1…

Python学习基础笔记十二——文件

1、目的&#xff1a;是要将数据永久地保存下来&#xff0c;就需要将数据永久保存在硬盘中。 2、概念&#xff1a;文件就是操作系统提供给应用程序来操作硬盘虚拟接口&#xff0c;用户或应用程序通过操作文件&#xff0c;可以将自己的数据永久地保存下来。 3、步骤&#xff1b; …

MACU-Net-用于精细分辨率遥感图像语义分割网络

摘要&#xff1a; 在本文中我们结合了由不同层次的U-Net生成的多尺度特征&#xff0c;设计了一个多尺度跳跃连接和基于非对称卷积的网络--MACU-Net。 网络具有以下几个优点1&#xff09;多尺度跳跃连接将低层和高层特征图中包含的语义特征结合并重新进行排列2&#xff09;非对…

一文搞懂傅里叶级数与变换

描述 这篇文章的目标&#xff1a;以最简单易懂的方式&#xff0c;让大家学会傅里叶变换&#xff01; 为什么要写一篇关于傅里叶变换相关知识的文章呢。有两个原因&#xff1a; 一、这个知识很有趣&#xff0c;可以理解它是一件炫酷的事情。在工作中&#xff0c;一次分享会同事…

BufferPool缓存机制

BufferPool缓存机制 1、更新数据流程 流程图 sql更新数据刷到磁盘前会经过serve层 连接器-管理连接和权限校验优化器-语法词法分析优化器-执行计划生成索引选择执行器-连接bufferPool 1.1 流程步骤 从磁盘加载数据到buffer pool&#xff0c;会先去判断要更新的数据所在数据…

Hantek6022BE 虚拟示波器

​ 0. Hantek 厂家提供的介绍 安装方法按照说明来。 很多人都说原厂的软件不好用&#xff0c;于是折腾就开始了&#xff1a; 1. VIRTINS Multi-Instrument 这个别人已经写的很详细了 大概需要准备 Multi-Ins 这软件&#xff0c;目前找到 3.7 的合用 菜单里 添加设备到库&a…

HTML+CSS详细知识点复习(上)

文章目录一、初识HTML1、标签概述二、初识CSS1、CSS核心基础2、设置文本样式3、高级特性4、CSS的优先级三、CSS选择器1、关系选择器四、盒子模型1、边框属性2、边距属性3、背景属性4、盒子的宽与高5、CSS3新增盒子模型属性一、初识HTML HTML&#xff08;超文本标记语言&#x…

用Python采集世界杯球队热搜数据 并发送邮箱通知

前言 嗨嗨&#xff0c;最近世界杯的热度可是一直在增长啊 待会就是 卡塔尔和塞内加尔打了 怎么说 还是有点期待结果的 趁现在有点无聊 就想着用Python采集世界杯球队热搜数据 顺便 发送邮箱通知 话不多说&#xff0c;马上开始 知识点 动态数据抓包requests发送请求json数据…

【Proteus仿真】【51单片机】智能雨刷器设计

文章目录一、主要功能二、硬件资源三、软件设计四、实验现象联系作者一、主要功能 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用LCD1602液晶模块、按键模块、雨滴传感器、ADC、LED模块等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示雨刷器当前模式、…

如何制定测试团队度量体系

1、前言 每当月底或一个季度结束&#xff0c;公司或项目都会进行考核指标的统计&#xff0c;来总结每个组员在这个阶段的工作产出与绩效成绩。 那么制定哪些指标最为标准&#xff0c;最为专业&#xff0c;同时针对整个项目组都是公平的&#xff0c;这个就需要每个公司或项目根…

Python入门

目录 一、Python安装及环境搭建 二、Python运用&#xff08;数据类型&#xff09; 基本数据类型 引用数据类型 一、Python安装及环境搭建 Python环境安装包下载 https://www.python.org/ https://www.python.org/downloads/windows/ Python开发工具PyCharm下载 https://www.…

南卡和FIIL 哪个更好用?南卡和FIIL CC nano蓝牙耳机对比测评

作为一个狂热的蓝牙爱好者&#xff0c;我也用了不少蓝牙耳机了&#xff0c;真的是对蓝牙耳机爱不释手。自从蓝牙耳机出现以来&#xff0c;我们都看到了它的迅速发展&#xff0c;尤其是这两年&#xff0c;蓝牙耳机越来越受欢迎&#xff0c;已经取代了传统的有线耳机&#xff0c;…

1-10嵌入式Linux系统开发与应用|嵌入式Linux|第三章 Linux编程环境

目录 1.掌握Linux常用的基本命令功能、语法结构和用法示例 1.1linux编程环境 1.1.1系统平台环境 linux平台特性 1.1.2开发工具环境 1.1.3基于文模式的开发平台 1.1.4集成开发平台EclipseCDT 1.1.5文档帮助环境 1.2常用编辑器 1.2.1VIM编辑器 1.VIM的模式 2.VIM的启…

爆冷?黑马?这次用python来给你推测一波.....

人生苦短 我用python 在刚刚结束的2022年卡塔尔世界杯E组第一轮一场比赛中&#xff0c; 德国队爆冷1:2不敌日本队。 上半场&#xff0c;日本队门将权田修一出击扑倒劳姆送点&#xff0c; 京多安主罚命中先拔头筹&#xff1b; 下半场&#xff0c;堂安律门前补射为日本队扳平…

如何裁剪视频画面?快来看看这个详细教程

有什么简单的方法可以裁剪视频&#xff1f;现在有很多小伙伴都会在社交平台上发布自己的视频内容&#xff0c;分享自己的日常&#xff0c;那在编辑视频的时候肯定是会对视频内容进行剪切的&#xff0c;那么怎么裁剪视频呢&#xff1f;有哪些简单的方法可以裁剪视频呢&#xff1…

Selenium基础 — TMLTestRunner测试报告

目录 1、HTMLTestRunner介绍 2、HTMLTestRunner的使用 3、测试报告示例 4、封装成模块 1、学习思路和方法 2、想学习却无从下手&#xff0c;该如何学习&#xff1f; 3、软件测试/自动化测试【全家桶装】学习中的工具、安装包、插件.... 4、有了安装包和学习资料&#x…

javaweb JAVA JSP零食销售系统购物系统ssm购物系统购物商城系统源码(ssm电子商务系统)网上零食在线销售

JSP零食销售系统购物系统ssm购物系统购物商城系统源码&#xff08;ssm电子商务系统&#xff09;网上零食在线销售

[网络工程师]-应用层协议-DNS

域名系统&#xff08;Domain Name System,DNS&#xff09;是把主机域名解析成IP地址的系统&#xff0c;解决了IP地址难记的问题。该系统由解析器和域名服务器组成。DNS主要基于UDP协议&#xff0c;较少情况下使用TCP协议&#xff0c;端口号均为53。域名系统由三部分组成&#x…