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

目录

堆的概念及结构

​编辑

堆的实现 

实现堆的接口:

堆的初始化:

堆的打印:

堆的销毁:

获取最顶的根数据:

 交换:

堆的插入:(插入最后)

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

堆的删除:(删除根)

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

堆排序


堆的概念及结构

如果有一个关键码的集合 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;
	}
}

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

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

相关文章

网络和Linux网络_1(网络基础)网络概念+协议概念+网络通信原理

目录 1. 网络简介 1.1 独立模式和互联网络模式 1.2 局域网LAN和广域网WAN 2. 协议和协议分层 2.1 协议的作用 2.2 协议分层 2.3 OSI七层模型 3.2 TCP/IP四层(五层)模型 3. 网络通信原理 3.1 协议报头 3.2 局域网和解包分用 3.3 广域网和跨网络 4. 网络中的地址 4…

vscode 快速打印console.log

第一步 输入这些 {// Print Selected Variabl 为自定义快捷键中需要使用的name&#xff0c;可以自行修改"Print Selected Variable": {"body": ["\nconsole.log("," %c $CLIPBOARD: ,"," background-color: #3756d4; padding:…

二十七、W5100S/W5500+RP2040树莓派Pico<iperf 测速示例>

文章目录 1 前言2 简介2 .1 什么是网络测速技术&#xff1f;2.2 网络测速技术的优点2.3 网络测速技术数据交互原理2.4 网络测速应用场景 3 WIZnet以太网芯片4 示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言…

【Verilog语法】

Verilog语法 1. Verilog语法1.1 拼接运算符1.2 运算符优先级1.3 注释1.4 关键字1.5 模块结构1.6 结构语句1.7 赋值语句1.8 条件语句1.9 状态机1.10 OSI七层模型 1. Verilog语法 1.1 拼接运算符 1.2 运算符优先级 1.3 注释 1.4 关键字 1.5 模块结构 1.6 结构语句 1.7 赋值语句 …

libusb获取Windows设备实例路径DevicePath

libusb 当前版本&#xff08;1.0.26&#xff09;libusb.h 头文件提供的接口似乎没有办法获取 Windows 平台相关的设备实例路径&#xff0c;其形如&#xff1a; \\?\usb#vid_04ca&pid_7070#5&20d34a76&0&6#{a5dcbf10-6530-11d2-901f-00c04fb951ed} 只是提供了…

2023测试职业生涯必看系列:手写web自动化测试框架教程 涵盖框架源码+视频教程以及搭建流程

前言 ​ 测试行业现在70%是以手工测试为主&#xff0c;那么只有20%是自动化测试&#xff0c;剩下的10%是性能测试。 有人可能会说&#xff0c;我现在做手工&#xff0c;我为什么要学自动化呢&#xff1f;我去学性能更好性能的人更少&#xff1f; 其实&#xff0c;性能的要求比…

openssh升级9.3p2

openssh升级9.3p2 openssh-rpms目录安装编译其他机器使用 将生成的rpm包传入响应服务器 openssh-rpms目录 github上有就是总是连接不上存百度网盘了 安装编译 unzip openssh-rpms-main.zip cd openssh-rpms-main/ yum -y groupinstall "Development Tools" yum -…

零基础快速上手STM32开发(手把手保姆级教程)

零基础快速上手STM32开发&#xff08;手把手保姆级教程&#xff09; 1. 前言 作为一名嵌入式工程师&#xff0c;STM32 是必须要学习的一款单片机&#xff0c;同时这款单片机资料足够多&#xff0c;而且比较简单&#xff0c;非常适合初学者入门。 STM32 是一款由 STMicroelec…

数据结构 1、基本概念 动态数组实现

一、大O表示法 判断一个算法的效率 难点 二、线性表 1.定义 2.数学定义 线性表是具有相同类型的n&#xff08;n>0&#xff09;个数据元素的有限序列&#xff08;a0,a1,a2,...,an&#xff09;,ai是表项&#xff0c;n是表长度 3.性质 4.线性表的基本操作 1.创建线性表 2…

Redis集群,你真的学会了吗?

目录 1、为什么引入集群 1.1、先来了解集群是什么 1.2、哨兵模式的缺陷 引入集群解决了什么问题 1.3、使用集群&#xff0c;如何存储数据 2、三种主流的分片方式【经典面试题】 2.1、哈希求余算法 2.1.1、哈希求余算法的介绍 2.1.2、哈希求余算法如何扩容 2.2、一致性…

No193.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

(只需三步)虚拟机上vm的ubuntu不能联上网怎么办

第一步&#xff1a;重启虚拟网络适配器 第二步&#xff1a;删掉网络适配器&#xff0c;重新添加 第三步&#xff1a;重启虚拟机网络服务器 sudo service network-manager stop sudo rm /var/lib/NetworkManager/NetworkManager.state sudo service network-manager start 再打…

eNSP-打开华为USG6000V1防火墙web管理页面方法

一、本地打开防火墙web管理页面 1.先在ensp中启动USG6000V1防火墙&#xff0c;启动后&#xff0c;需要输入原始username和password&#xff08;username&#xff1a;admin&#xff0c;password&#xff1a;Admin123&#xff09;&#xff0c;并修改原始密码后&#xff0c;才能配…

由浅入深学习统计学 -集中趋势的量度

由浅入深学习统计学 -集中趋势的量度 均值 &#xff08;通俗来说是平均数&#xff09; 计算公式 均值在对称数据中才有参考性。 异常数据会导致出现&#xff0c;向左偏移或者向右偏移 中位数 - &#xff08;也是属于平均数的一种&#xff09; 当偏移数据和异常数据使得均值产…

大手笔!吴恩达一口气开放了 3 个 AIGC 教程。。

一个月前&#xff0c;DeepLearning.ai 创始人吴恩达与 OpenAI 开发者 Iza Fulford 联手推出了一门面向开发者的技术教程&#xff1a;ChatGPT 提示工程。 该教程总共分为 9 个章节&#xff0c;总一个多小时&#xff0c;里面主要涵盖&#xff1a;提示词最佳实践、评论情感分类、…

Centos7安装Jenkins

Jenkins官方网址&#xff1a;https://www.jenkins.io/zh/ 关闭防火墙 systemctl stop firewalld && systemctl disable firewalld && iptables -Fsed -i s/enforcing/disabled/ /etc/selinux/config && setenforce 0安装JDK 检索JDK可用包 yum sear…

威海广泰-002111 三季报分析(20231109)

威海广泰-002111 基本情况 公司名称&#xff1a;威海广泰空港设备股份有限公司 A股简称&#xff1a;威海广泰 成立日期&#xff1a;2002-08-30 上市日期&#xff1a;2007-01-26 所属行业&#xff1a;专用设备制造业 周期性&#xff1a;0 主营业务&#xff1a;航空产业、消防产业…

错误:FUNCTION simple_notebook.count does not exist.解决方法

0 引入问题 小王&#xff1a;你这个数据有问题啊&#xff0c;有时候还会报错 小腾&#xff1a;怎么会有问题呢&#xff0c;代码写的一点毛病也没有 小王&#xff1a;没问题怎么会报错&#xff0c;你赶紧看看&#xff0c;项目上线甲方看到了报给老板咱俩就寄了 小腾&#xff1a…

基于LangChain+ChatGLM2-6B+embedding构建行业知识库

目的&#xff1a;最近在探索大模型本地化部署知识库实现行业解决方案&#xff0c;安装过程记录&#xff0c;分享给需要的同学&#xff0c;安装前确定好各组件的版本非常重要&#xff0c;避免重复安装走老路。 经过查阅大量资料&#xff0c;目前可以分为以下两种方案 方案一&am…

【npm 错误】:npm ERR! code ERESOLVE、npm ERR! ERESOLVE could not resolve问题

用过npm的小伙伴都会有这么一个情况出现&#xff0c;就是npm install /npm install xxxx 会出现改一连串的错误&#xff0c;如下&#xff1a; 解决办法&#xff1a; 只要在npm install后面加上--legacy-peer-deps就可以解决问题,安装插件也一样 npm install --legacy-peer-dep…