007 数据结构_堆——“C”

2023-10-28

前言

本文将会向您介绍关于堆Heap的实现

具体步骤

tips:本文具体步骤的顺序并不是源代码的顺序

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _a;
	int _size;
	int _capacity;
}Heap;

初始化

void HeapCreate(Heap* hp, HPDataType* a, int n)
{
	hp->_a = NULL;
	hp->_size = 0;
	hp->_capacity = 0;
}

扩容

解析:扩容的逻辑很简单,没什么可讲的,要注意的点有这里不要使用malloc,当再次需要扩容的时候,malloc函数只会分配新的内存空间,不会复制原有内存空间的内容,realloc函数会在分配新的内存空间时,将原有内存内容复制到新的内存空间中,并释放原有空间内容
//扩容
void CheckCapacity(Heap* hp)
{
if (hp->_capacity == hp->_size)
{
	int newcapacity = hp->_capacity == 0 ? 4 : hp->_capacity * 2;
	HPDataType* tmp = (HPDataType*)realloc(hp->_a, sizeof(HPDataType) * newcapacity);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	hp->_a = tmp;
	hp->_capacity = newcapacity;
}
}

判空

// 堆的判空
bool HeapEmpty(Heap* hp)
{
	assert(hp);
	return hp->_size == 0;
}

交换

解析:这里提供了一个swap函数用于向上调整和向下调整时交换数据

//交换
void swap(int* a, int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

插入

每次插入的数据都会进行向上调整,将一串数据建成小堆/大堆

// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	CheckCapacity(hp);
	hp->_a[hp->_size] = x;
	hp->_size++;
	Adjustup(hp->_a, hp->_size - 1);
}

向上调整

当插入数据时,注意每次插入一个数据都会向上调整(直到根结点)图中这里只是将结构画了出来助于理解,真实的情况中并不是向右边的堆图一样

在这里插入图片描述

以小堆为例,当a[child] <a[parent]就将二者交换,并将parent 赋值给child,并利用新的child计算出新的parent,这样的做法是可以向上进行调整。这里若是将a[child] <a[parent]变成a[child] >a[parent]就是大堆

//向上调整
void Adjustup(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
	if (a[child] < a[parent])
	{
		swap(a, &a[child], &a[parent]);
		child = parent;
		parent = (child - 1) / 2;
	}
	else
	{
		break;
	}
	}
}

删除

解析:需要删除堆顶的数据,但是如果挪动数据删除堆顶的数据,可能会导致可能会导致堆的性质不满足,影响堆的正确性和效率。因此需要交换堆顶与末尾的数据,再将末尾的数据删除,这样一来就可以删除掉堆顶的数据,但是有个问题:将堆尾的数据调整到了堆顶,需要进行向下调整
// 堆的删除 删除堆顶
void HeapPop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	swap(hp->_a, &(hp->_a[0]), &(hp->_a[hp->_size - 1]));
	--hp->_size;
	//向下调整
	AdjustDown(hp->_a, hp->_size, 0);
}

向下调整

解析:当我们删除堆顶数据的时候进行向下调整,n:堆的数据个数,利用parent计算出child下标

//向下调整
void AdjustDown(int* a, int n, int parent)
{
	//计算左child,相当于(child = leftchild)
	int child = parent * 2 + 1;
	//当逐步地向下调整,child会越来越大,child不能超过堆数据个数
	while (child < n)
	{
	//向下调整的时候右child可能越界
	//找左右child小的那一个进行与a[parent]比较
	if (child + 1 < n && a[child + 1] < a[child])
	{
		//若是默认的child(leftchild) > a[child + 1]
		++child;
	}
	//可调整<(小堆)为>(大堆)
	if (a[child] < a[parent])
	{
		swap(a, &a[child], &a[parent]);
		//向下调整
		parent = child;
		child = parent * 2 + 1;
	}
	else
	{
		break;
	}
	}
}

销毁

// 堆的销毁
void HeapDestory(Heap* hp)
{
	free(hp->_a);
	hp->_a = NULL;
	hp->_capacity = 0;
	hp->_size = 0;
}

获取堆顶数据

// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	return hp->_a[0];
}

获取个数

// 堆的数据个数
int HeapSize(Heap* hp)
{
	assert(hp);
	return hp->_size;
}

代码+测试

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _a;
	int _size;
	int _capacity;
}Heap;

// 堆的构建
void HeapCreate(Heap* hp, HPDataType* a, int n)
{
	hp->_a = NULL;
	hp->_size = 0;
	hp->_capacity = 0;
}
//扩容
void CheckCapacity(Heap* hp)
{
if (hp->_capacity == hp->_size)
{
	int newcapacity = hp->_capacity == 0 ? 4 : hp->_capacity * 2;
	HPDataType* tmp = (HPDataType*)realloc(hp->_a, sizeof(HPDataType) * newcapacity);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	hp->_a = tmp;
	hp->_capacity = newcapacity;
}
}
// 堆的判空
bool HeapEmpty(Heap* hp)
{
	assert(hp);
	return hp->_size == 0;
}
//交换
void swap(int* a, int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//向下调整
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
	if (child + 1 < n && a[child + 1] < a[child])
	{
		++child;
	}
	if (a[child] > a[parent])
	{
		swap(a, &a[child], &a[parent]);
		parent = child;
		child = parent * 2 + 1;
	}
	else
	{
		break;
	}
	}

}
//向上调整
void Adjustup(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
	if (a[child] > a[parent])
	{
		swap(a, &a[child], &a[parent]);
		child = parent;
		parent = (child - 1) / 2;
	}
	else
	{
		break;
	}
	}
}
// 堆的销毁
void HeapDestory(Heap* hp)
{
	free(hp->_a);
	hp->_a = NULL;
	hp->_capacity = 0;
	hp->_size = 0;
}
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	CheckCapacity(hp);
	hp->_a[hp->_size] = x;
	hp->_size++;
	Adjustup(hp->_a, hp->_size - 1);
}
// 堆的删除 删除堆顶
void HeapPop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	swap(hp->_a, &(hp->_a[0]), &(hp->_a[hp->_size - 1]));
	--hp->_size;
	//向下调整
	AdjustDown(hp->_a, hp->_size, 0);
}
// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	return hp->_a[0];
}
// 堆的数据个数
int HeapSize(Heap* hp)
{
	assert(hp);
	return hp->_size;
}
int main()
{
	int arr[] = { 60, 32, 50, 65, 70, 100};
	Heap hp;
	HeapCreate(&hp, arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		HeapPush(&hp, arr[i]);
	}
	while (!HeapEmpty(&hp))
	{
		int top = HeapTop(&hp);
		printf("%d\n", top);
		HeapPop(&hp);
	}
}

小结

本文的分享就到这里啦,如果本文存在疏漏或错误的地方还请您能够指出!

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

007 数据结构_堆——“C” 的相关文章

  • 准确记录用户观看视频内容时长

    文章目录 问题的产生 一 从最简单的开始 二 天真可爱法 三 录点法 四 打点法 五 暴力打点法 六 小结 七 大结 问题的产生 to be or not to be that is a question 不是问题解决不了 只是你自己不够努
  • 事件派发代码

    bool QCoreApplication sendEvent QObject receiver QEvent event Q TRACE QCoreApplication sendEvent receiver event event gt
  • 没有扩容机器,抗住了70多倍的流量增长

    欢迎大家前往腾讯云社区 获取更多腾讯海量技术实践干货哦 作者 黄希彤 腾讯云专家工程师 从2012年开始 我们就吧腾讯公司内各个业务的404页面导流给宝贝回家 从2013年开始 我们更开放了404寻亲接入给第三方网站 这些导流给宝贝回家论坛
  • 第14节 在VS中关闭安全周期检查sdl

    项目 gt 属性 gt C C gt 常规 gt SDL检查 gt 否
  • C语言中符号表示什么意思?

    C语言中 gt gt lt lt 分别表示什么意思 举例说明 1 C语言中的 gt gt 意思为 右移后赋值 代码示例为 x 8 x gt gt 3 右移后结果为 00000000 00000000 00000000 00000001 2
  • OPenCV入门学习笔记(5)人脸检测

    检测的一般步骤 加载xml级联分类器 读入图片 灰度化处理图片 进行检测 加载xml级联分类器 face detector cv2 CascadeClassifier haarcascade frontalface default xml

随机推荐

  • 2023华为OD机试真题-狼羊过河(JAVA、Python、C++)

    题目描述 一农夫带着m只羊 n只狼过河 农夫有一条可载x只狼 羊的船 农夫在时或者羊的数量大于狼时 狼不会攻击羊 农夫在不损失羊的情况下 运输几次可以完成运输 返程不计入次数 输入描述 输入参数为 m n x m 为羊的数量 n为狼的数量
  • 乐高ev3编程 c语言,乐高ev3编程软件下载-乐高EV3机器人编程软件lego mindstorms ev31.0 官方版 - 极光下载站...

    LEGO MINDSTORMS EV3是乐高EV3机器人编程软件 乐高ev3编程软件是乐高头脑风暴EV3机器人配套的编程软件 包含多个有趣的机器人编程任务 拥有简单易用的编程界面 让您您轻松探索并操纵乐高EV3机器人 让机器人服从您的命令
  • 51单片机(硬件结构)并行I/O端口

    I O端口结构及功能 1 MCS 51单片机有4个8位并行I O端口 P0 P1 P2 P3 2 每个口包含 锁存器 输出驱动器 输入缓存器 3 具有字节寻址和位寻址功能 4 在访问片外扩展存储器时 低8位地址和数据由P0口 分时传送 高8
  • DDR3总结笔记

    注 学习 交流就在博主的个人weixin公众号 FPGA动力联盟 留言或直接 博主weixin fpga start 私信 完整的参考工程源码在某宝有售 https item taobao com item htm ft t id 6832
  • JAVA形参可变数量参数

    public class test public void info int nums for int num nums System out println num public static void main String args
  • linux /etc/profile bashrc bash_profile

    文件 etc profile bashrc 和 bash profile 的使用区别 etc profile 全局 环境变量等 在机器重启后执行一次 用于设置环境变量 更改一些内核参数等命令 etc bashrc 全局登陆 变量 如 ali
  • 为Android添加HAL模块

    1 每个硬件抽象层模块在内核中都对应一个驱动程序 硬件抽象层模块就时通过这些驱动程序来访问硬件设备的 它们是通过读写设备文件来进行通信的 硬件抽象层中的模块接口源文件一般保存在hardware libhardware目录中 为了方便起见 我
  • 关于exe文件无法执行的解决方式小结

    昨天学习时候用到Apache 下载安装之后 用对应的exe文件无法打开 服务器一直打不开 我就好奇怎么样才能解决这个问题 先在网上百度了一些方法 通过修改注册表方式 步骤如下 新建记事本 将下面这段代码保存进去 然后另存为将其修改为恢复可执
  • ovs tag

    ovs tag 下发正常转发流表 sh ovs ofctl add flow s1 action normal action NORMAL的流表意思是该交换机配置成一个正常传统交换机工作 ovs交换机有两种工作模式 SDN模式和传统模式 传
  • python assert用法

    1 assert语句用来声明某个条件是真的 2 如果你非常确信某个你使用的列表中至少有一个元素 而你想要检验这一点 并且在它非真的时候引发一个错误 那么assert语句是应用在这种情形下的理想语句 3 当assert语句失败的时候 会引发一
  • Qt学习笔记——界面文件的使用

    一 界面文件的使用 1 独立的ui文件 使用uic命令把ui文件编译成 h文件 uic xxx ui o xxx h 2 在集成开发环境中使用 1 Qt构造器会把xxx ui文件生成 ui xxx h 文件 且会有一个xxx h xxx c
  • (转载)STM32与LAN9252构建EtherCAT从站

    目录 一 项目简介 EtherCAT及项目简述 LAN9252工作模式 整体开发流程 移植要处理的问题 代码层面的工作 开发中使用的工具 二 SSC的使用 SSC简介和下载 SSC构建协议栈文件和XML 三 LAN9252的XML文件 Et
  • postgresql常用函数>序列函数nextval():设置主键自动增长

    主键一般设置为Integer类型 并且自动增长 起始值为1 增量为1 有两种方法 法一 在建表时 nextval 表名 主键 seq regclass 法二 如果表已经建好 CREATE SEQUENCE 表名 主键 seq START W
  • anaconda jupyter-notebook

    文章目录 仓库镜像配置 新建python 环境 jupyter notebook 仓库镜像配置 conda config add channels https mirrors tuna tsinghua edu cn anaconda pk
  • 程序员必备的25个好网站汇总

    一 技术提升 0 GitHub 程序员托管代码的平台 很多开发者都会在上面找各种各样的开源项目来学习 阿里 腾讯 字节跳动 美团 Google Micosoft等国内外大厂都有自己的Github开源库 1 StackOverflow 一个强
  • 蓝桥杯单片机学习日记4-串口接收与发送,解决串口引脚与按键引脚冲突

    此片文章用于记录蓝桥杯单片机的学习 串口的发送与接收较为简单 主要是字节和字符串的发送与接收 直接上程序 串口初始化 void UartInit void 9600bps 11 0592MHz SCON 0x50 8位数据 可变波特率 AU
  • MySQL数据库是非关系_MySQL(数据库)基础知识、关系型数据库yu非关系型数据库、连接认证...

    什么是数据库 数据库 Database 存储数据的仓库 高效地存储和处理数据的介质 介质主要是两种 磁盘和内存 数据库系统 DBS Database System 是一种虚拟系统 将多种内容关联起来的称呼 DBS DBMS DB DBMS
  • 汇编语言(王爽)第四版学习1

    第一章 机器语言 0 1 简单语句 mov ax bx 汇编语言组成 1 汇编指令 机器码的助记符 有对应的机器码 2 伪指令 没有对应的机器码 由编译器执行 计算机并不执行 3 其他符号 如 等 由编译器识别 没有对应的机器码 存储器 内
  • SpringCloud微服务---Nacos配置中心

    1 Nacos Config 服务配置 1 1 服务配置中心介绍 首先我们来看一下 微服务架构下关于配置文件的一些问题 1 配置文件相对分散 在一个微服务架构下 配置文件会随着微服务的增多变的越来越多 而且分散在各个微服务中 不好统一配置和
  • 007 数据结构_堆——“C”

    前言 本文将会向您介绍关于堆Heap的实现 具体步骤 tips 本文具体步骤的顺序并不是源代码的顺序 typedef int HPDataType typedef struct Heap HPDataType a int size int