【数据结构】堆(Heap):堆的实现、堆排序

news2024/12/27 22:01:23

目录

堆的概念及结构

​编辑

堆的实现 

实现堆的接口:

堆的初始化:

堆的打印:

堆的销毁:

获取最顶的根数据:

 交换:

堆的插入:(插入最后)

向上调整:(这次用的是小堆)

堆的删除:(删除根)

向下调整:(这次用的小堆)

堆排序


堆的概念及结构

如果有一个关键码的集合 K = { , , , ,},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: <= 且 <= ( >= 且 >= ) i = 0, 1 , 2…,则称为小堆 ( 或大堆 ) 。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

小根堆:父亲节点大于等于孩子节点

大根堆:父亲节点小于等于孩子节点 

 

堆的实现 

实现堆的接口:

#define CRT_SECURE_NO_WARNING 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<stdbool.h>

//二叉树-堆
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;


void AdjustUp(HPDataType* a, int child);

void AdjustDown(HPDataType* a, int n, int parent);

//交换
void Swap(HPDataType* p1, HPDataType* p2);
//打印
void HeapPrint(HP* php);
//初始化
void HeapInit(HP* php);
//
void HeapInitArray(HP* php, int* a, int n);
//销毁
void HeapDestroy(HP* php);
//插入
void HeapPush(HP* php, HPDataType x);
//删除
void HeapPop(HP* php);
//返回最顶数据
HPDataType HeapTop(HP* php);
//判空
bool HeapEmpty(HP* php);

堆的初始化:

//初始化
void HeapInit(HP* php)
{
	assert(php);

	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}

堆的打印:

void HeapPrint(HP* php)
{
	assert(php);

	//最后一个孩子下标为size-1
	for (size_t i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
	}
	printf("\n");
}

堆的销毁:

//销毁
void HeapDestroy(HP* php)
{
	assert(php);

	free(php->a);
	php->a = NULL;
	php->size = php->capacity = 0;
}

获取最顶的根数据:

//获取根数据
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}

 交换:

void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

堆的插入:(插入最后)

先考虑扩容,将数据插到最后,再用向上调整法。

//插入数据
void HeapPush(HP* php, HPDataType x)
{
	assert(php);

	//扩容
	if (php->size == php->capacity)//有效元素个数和容量是否相等
	{
		//相等的情况分两种:1.容量为0,先扩4个sizeof   2.容量占用满了,扩2个
		int newCapacity =php->capacity == 0 ? 4 : php->capacity * 2;
		//返回扩容后的内存新地址							//扩容后的新大小
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newCapacity);
		
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		//扩容后的新地址
		php->a = tmp;
		//新容量
		php->capacity = newCapacity;
	}

	//   php->size下标位置  先将x放最后,后面再调整
	php->a[php->size] = x;
	//   有效数据++
	php->size++;
	//   向上调整     //size-1为新插入数据的下标
	AdjustUp(php->a, php->size - 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 = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

堆的删除:(删除根)

先判空,看下是否还有元素可以删除。根数据先和最后一个孩子交换位置,孩子再向下调整。

//删除
void HeapPop(HP* php)
{
	assert(php);
	//确保有元素可删
	assert(php->size > 0);

	//最后一个孩子和要删除的根交换
	Swap(&php->a[0], &php->a[php->size - 1]);
	//有效元素size减减,相当于删除了交换后的原来的根
	--php->size;

	//删除后向下调整
	AdjustDown(php->a, php->size, 0);

}

向下调整:(这次用的小堆)

//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	//n下标位置已经没有数了
	while (child < n)
	{
		//选小的孩子往上浮(小堆)
		if (child + 1 < n && a[child + 1] < a[child])
		{
			++child;
		}
		//若小的孩子都小于父,则交换
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			//交换后下来的数重新变成parent,继续向下调整
			parent = child;
			child = parent * 2 + 1;
		}
	}
}

堆排序

1. 建堆
升序:建大堆
降序:建小堆
2. 利用堆删除思想来进行排序
如,建的大堆排升序,可以用堆删除思想向下调整法将栈顶和最后一个元素交换,依次将最大的次大的......往后放,就达到了升序排列。
void HeapSort(int* a, int n)
{
	//建堆  这里可以选建大堆还是小堆
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}

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

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

相关文章

解决Chrome无法自动同步书签

前提&#xff1a;&#xff08;要求能正常访问google&#xff09; 准备一个谷歌账号 安装Chrome浏览器 开启集装箱插件&#xff08;或者其他能访问谷歌的工具&#xff09; 步骤&#xff1a;&#xff08;使用集装箱插件/能正常访问谷歌的其他工具&#xff09; 下载安装使用“集…

as启动Internal error. Please refer to https://code.google.com/p/android/issues

打开AndroidStudio时遇到nternal error. Please report to https://code.google.com/p/android/issues 解决方法&#xff1a; 1、在AndroidStudio项目安装目录的/Applications/Android\ Studio.app/Contents/bin/idea.properties 文件中最后一行添加disable.android.first.runt…

云流量回溯的重要性和应用

云流量回溯是指利用云计算和相关技术来分析网络流量、数据传输或应用程序操作的过程。这个过程包括了对数据包、通信模式和应用程序性能的审查和跟踪。本文将介绍云流量回溯重要性和应用! 1、网络安全: 云流量回溯是网络安全的重要组成部分。通过监测和回溯网络流量&#xff0c…

MySQL(15):存储过程与函数

存储过程概述 含义&#xff1a; 存储过程的英文是 Stored Procedure 。它的思想很简单&#xff0c;就是一组经过 预先编译 的 SQL 语句的封装。 执行过程&#xff1a; 存储过程预先存储在 MySQL 服务器上&#xff0c;需要执行的时候&#xff0c;客户端只需要向服务器端发出调用…

Shotcut for Mac/Win:免费的开源视频编辑软件

Shotcut 是一款免费的开源视频编辑软件&#xff0c;允许用户为各种目的编辑和创建视频。它适用于 Windows、Mac 和 Linux 操作系统。Shotcut 具有用户友好的界面&#xff0c;并提供一系列功能&#xff0c;例如支持多种视频格式、音频过滤器和视频效果。 Shotcut的一些主要功能…

020线上线下融合商业模式 新零售系统定制开发

020线上线下融合商业模式将传统的线下实体店和线上电子商务相结合&#xff0c;通过双通道销售、互联网服务等方式&#xff0c;实现线上线下渠道的整合与协同发展。这种商业模式的核心在于通过整合线上线下资源&#xff0c;提供更优质的产品和服务&#xff0c;增强消费者体验和提…

全志R128平台SPI与DBI点屏性能大对比

SPI 与 DBI 性能对比 R128 平台的 SPI 接口参数如下 全双工同步串行接口Master/Slave模式可配置支持最大96MHz时钟频率支持SPI Mode0/1/2/3片选和时钟的极性和相位可配置5个时钟源支持中断或DMA传输支持多片选支持Standard Single/Dual/Quad SPI&#xff0c;FIFO深度64B支持B…

Monarch Mixer: A Simple Sub-Quadratic GEMM-Based Architecture

Monarch Mixer: A Simple Sub-Quadratic GEMM-Based Architecture 发于 2023年AI顶会 NeurIPS。 sub-quadratic primitive(次二次原语) GEMMs&#xff08;General Matrix Multiply algorithms&#xff09;是指在许多核心系统上执行的通用矩阵乘法操作的模型。 “causal model…

安全框架SpringSecurity-2(集成thymeleaf集成验证码JWT)

一、SpringSecurity 集成thymeleaf ①&#xff1a;复制并修改工程 复制04_spring_security并重命名为05_spring_security_thymeleaf ②&#xff1a;添加配置和依赖 添加thymeleaf依赖 <dependency><groupId>org.springframework.boot</groupId><artif…

岗前酒精检测仪

岗前酒精检测仪&#xff1a;集“酒精检测智能测温人脸考勤”三合一智能检测仪。 酒精检测功能&#xff1a;采用电化学传感器检测检测酒精浓度&#xff0c;具有吹气中断及吹气流量侦测&#xff0c;吹气防欺骗设计&#xff0c;吹气温度及吸气侦测&#xff1b;响应时间≤20毫秒&am…

编程实现ROS话题通信——手撕 turtlesim 节点

一、实验任务 任务要求如下&#xff1a;使用 C 编程实现1个ROS节点&#xff0c;订阅 turtlesim 例程中 turtle_teleop_key 节点发出的消息&#xff0c;并将此消息进行一定的转换后&#xff08;自行定义&#xff0c;如将数值按适当比例缩小、运动方向变换等&#xff09;&#xf…

【CANN】SPI通信、I2C通信

文章目录 一、SPI通信1.SPI通信2.SPI通信原理3.CPOL时钟极性、CPHA时钟相位 二、I2C通信1、I2C通信2、I2C通信原理2.1、I2C的起始和结束条件2.2、数据传送格式 总结 一、SPI通信 1.SPI通信 SPI是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接…

@Async注解的坑

问题描述 一个方法调用另一个方法(该方法使用Async注解)在同一个类文件中&#xff0c;该注解会失效&#xff01; 问题复现 TestAsyncController 类 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; im…

el-table解决数据过少小于高度有留白的问题

问题:给el-table设置个高度,高度为500px,之后就添加如下4条数据,那么底部就没数据,直接就空白了,本文章就是为了解决这个问题,如果底部留白那么就添加几条空数据就行了.如果数据已达到高度了那么就不会留白了 1.效果 这个空列可以根据高度来决定添加几个空格子去铺满列表&…

基于头脑风暴算法优化概率神经网络PNN的分类预测 - 附代码

基于头脑风暴算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于头脑风暴算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于头脑风暴优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

数字三角形模型 笔记

方格取数 走两次的最大值 f[k][i1][i2]来表示 k i1 j1 i2 j2; 每一个状态可由四种状态转换来&#xff0c;分别为 第一条路走下&#xff0c;第二条路走下 第一条路走下&#xff0c;第二条路走右 第一条路走右&#xff0c;第二条路走下 第一条路走右&#xff0c;第二条…

一文了解多线程实现交替执行

本文已收录于专栏 《Java》 目录 背景介绍实现方式总结提升 背景介绍 有一个需求是要求多个线程去执行任务&#xff0c;需要每个线程都执行一次之后再继续执行&#xff0c;也就是说每个线程交替去执行任务。举个例子来说&#xff0c;有两个线程&#xff0c;一个输出字母&#x…

全球步入VUCA时代,FinOps如何成为云计算下一个关键性机会?

科技云报道原创。 俗话说&#xff0c;省下来的就是利润。在全球都处于VUCA的时代&#xff0c;更是如此。 近年来&#xff0c;随着云计算的广泛应用,云成本管理成为企业关注的重点。FinOps&#xff08;云成本优化&#xff09;作为一种新兴的云成本管理方式&#xff0c;吸引了行…

基于蝴蝶算法优化概率神经网络PNN的分类预测 - 附代码

基于蝴蝶算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于蝴蝶算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于蝴蝶优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

成都爱尔周进院长解析高度近视可能引发哪些疾病

当代各类人群面对电脑、手机屏幕的时长显著增加&#xff0c;导致用眼过度、疲劳&#xff0c;视觉质量下降&#xff0c;近视人群越来越多。而当父母有一方为高度近视甚至可能将近视遗传给孩子。 目前&#xff0c;全球近视人数约25亿&#xff0c;中国近视人群人数多达6亿。据预测…