【数据结构】堆(一)

news2024/9/22 22:36:43

😛作者:日出等日落

📘 专栏:数据结构

                         如果我每天都找出所犯错误和坏习惯,那么我身上最糟糕的缺点就会慢慢减少。这种自省后的睡眠将是多么惬意啊。

目录

🎄堆的概念及结构:

 🎄堆的实现:

✔基本接口函数:

✔结构体:

✔HeapInit函数: 

✔HeapDestory函数:

✔HeapPrint函数: 

✔HeapPush函数:

✔HeapPop函数:

✔HeapTop函数:

🎄完整代码:

✔Heap.h:

✔Heap.c:

✔Text.c:


🎄堆的概念及结构:

如果有一个关键码的集合K = { k0,k1 ,k2 ,…,k(n-1) },把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K(2*i+1)且 Ki <= K(2*i+2) (Ki >= K(2*i+1)且Ki >= K(2*i+2)) i = 0,1, 2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值
  • 堆总是一棵完全二叉树
  • 简单来说:
  • 父节点都比其的子节点大的完全二叉树叫做大堆。
  • 父节点都比其的子节点小的完全二叉树叫做小堆。

如图: 

 

 🎄堆的实现:

✔基本接口函数:

//堆的初始化
void HeapInit(HP* hph);

//堆的销毁
void HeapDestory(HP* hph);

//堆的打印
void HeapPrint(HP* hph);

// 堆的插入
void HeapPush(HP * hph, HPDataType x);

// 堆的删除
void HeapPop(HP* hph);

// 取堆顶的数据
HPDataType HeapTop(HP* hph);

// 堆的数据个数
int HeapSize(HP* hph);

// 堆的判空
int HeapEmpty(HP* hph);

✔结构体:

typedef int HPDataType;
typedef struct heap
{
	HPDataType* a;
	int capacity;
	int size;
}HP;

✔HeapInit函数: 

//堆的初始化
void HeapInit(HP* hph)
{
	assert(hph);
	hph->a = NULL;
	hph->capacity = hph->size = 0;
}

✔HeapDestory函数:

//堆的销毁
void HeapDestory(HP* hph)
{
	assert(hph);
	free(hph->a);
	hph->a = NULL;
	hph->capacity = 0;
	hph->size = 0;
}

✔HeapPrint函数: 

//堆的打印
void HeapPrint(HP* hph)
{
	for (int i = 0; i < hph->size; ++i)
	{
		printf("%d ", hph->a[i]);
	}
	printf("\n");
}

✔HeapPush函数:

capacity==size时扩容(包括初始化的方案),当size==0时,扩容4个空间,否则扩容二倍的空间,capacity也跟着扩大,当push后size++

 Swap交换函数:

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

//向上调整
//child和parent都是下标
void AdjusUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

// 堆的插入
void HeapPush(HP* hph, HPDataType x)
{
	assert(hph);
	//扩容
	if (hph->capacity == hph->size)
	{
		int newcapacity = hph->capacity == 0 ? 4 : hph->capacity * 2;
		HPDataType* tmp = (HPDataType* )realloc(hph->a, sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail:");
			exit(-1);
		}
		hph->a = tmp;
		hph->capacity = newcapacity;
	}
	hph->a[hph->size] = x;
	hph->size++;

	//向上调整
	AdjusUp(hph->a, hph->size - 1);
}

✔HeapPop函数:

出堆顶的元素,让第一个位置的值和最后一个位置的值交换,再size--就相当于删除了,但交换上去的值在根节点的位置上,我们无法维持是大堆的情况,因此还需要向下调整Ajustdown。

 

//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1< n && a[child] < a[child + 1])
		{
			child = child + 1;
		}
		//child 大于 parent 就交换
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// 堆的删除
void HeapPop(HP* hph)
{
	assert(hph);
	assert(!HeapEmpty(hph));
	Swap(&hph->a[0], &hph->a[hph->size - 1]);

	hph->size--;
	AdjustDown(hph->a, hph->size, 0);
}

✔HeapTop函数:

// 取堆顶的数据
HPDataType HeapTop(HP* hph)
{
	assert(hph);
	assert(hph->size > 0);
	return hph->a[0];
}

🎄完整代码:

✔Heap.h:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>

typedef int HPDataType;
typedef struct heap
{
	HPDataType* a;
	int capacity;
	int size;
}HP;

//堆的初始化
void HeapInit(HP* hph);

//堆的销毁
void HeapDestory(HP* hph);

//堆的打印
void HeapPrint(HP* hph);

// 堆的插入
void HeapPush(HP * hph, HPDataType x);

// 堆的删除
void HeapPop(HP* hph);

// 取堆顶的数据
HPDataType HeapTop(HP* hph);

// 堆的数据个数
int HeapSize(HP* hph);

// 堆的判空
int HeapEmpty(HP* hph);

✔Heap.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include "heap.h"


//堆的打印
void HeapPrint(HP* hph)
{
	for (int i = 0; i < hph->size; ++i)
	{
		printf("%d ", hph->a[i]);
	}
	printf("\n");
}

//堆的初始化
void HeapInit(HP* hph)
{
	assert(hph);
	hph->a = NULL;
	hph->capacity = hph->size = 0;
}

//堆的销毁
void HeapDestory(HP* hph)
{
	assert(hph);
	free(hph->a);
	hph->a = NULL;
	hph->capacity = 0;
	hph->size = 0;
}
void Swap(HPDataType* p1, HPDataType* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//向下调整
//child和parent都是下标
void AdjusUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

// 堆的插入
void HeapPush(HP* hph, HPDataType x)
{
	assert(hph);
	//扩容
	if (hph->capacity == hph->size)
	{
		int newcapacity = hph->capacity == 0 ? 4 : hph->capacity * 2;
		HPDataType* tmp = (HPDataType* )realloc(hph->a, sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail:");
			exit(-1);
		}
		hph->a = tmp;
		hph->capacity = newcapacity;
	}
	hph->a[hph->size] = x;
	hph->size++;

	//向下调整
	AdjusUp(hph->a, hph->size - 1);
}

//向上调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1< n && a[child] < a[child + 1])
		{
			child = child + 1;
		}
		//child 大于 parent 就交换
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// 堆的删除
void HeapPop(HP* hph)
{
	assert(hph);
	assert(!HeapEmpty(hph));
	Swap(&hph->a[0], &hph->a[hph->size - 1]);

	hph->size--;
	AdjustDown(hph->a, hph->size, 0);
}

// 取堆顶的数据
HPDataType HeapTop(HP* hph)
{
	assert(hph);
	assert(hph->size > 0);
	return hph->a[0];
}

// 堆的数据个数
int HeapSize(HP* hph)
{
	assert(hph);
	return hph->size;
}

// 堆的判空
int HeapEmpty(HP* hph)
{
	assert(hph);
	return hph->size == 0;
}

✔Text.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include "heap.h"

void Heap()
{
	int arry[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
	HP hph;
	HeapInit(&hph);
	HeapPrint(&hph);
	for (int i = 0; i < sizeof(arry) / sizeof(int); i++)
	{
		HeapPush(&hph, arry[i]);
	}
	HeapPrint(&hph);
	HeapPush(&hph, 100);
	HeapPrint(&hph);
	HeapPop(&hph);
	HeapPrint(&hph);

	HeapDestory(&hph);
}
void TestHeap2()
{
	int array[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
	HP hp;
	HeapInit(&hp);
	for (int i = 0; i < sizeof(array) / sizeof(int); ++i)
	{
		HeapPush(&hp, array[i]);
	}

	while (!HeapEmpty(&hp))
	{
		printf("%d ", HeapTop(&hp));
		HeapPop(&hp);
	}

	HeapDestroy(&hp);
}

int main()
{
	TestHeap2();
	return 0;
}

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

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

相关文章

万丈高楼平地起 AI帮你做自己

AI的自我介绍 AI是人工智能&#xff08;Artificial Intelligence&#xff09;的英文缩写&#xff0c;是一种通过计算机技术模拟和延伸人类智能的技术和应用。AI可以被看作是一种智能化的计算机程序或系统&#xff0c;它能够自动地执行一些需要人类智能才能完成的任务&#xf…

JavaEE初阶学习:初识网络

1.网络发展史 1.独立模式 独立模式:计算机之间相互独立&#xff1b; 2.网络互连 随着时代的发展&#xff0c;越来越需要计算机之间互相通信&#xff0c;共享软件和数据&#xff0c;即以多个计算机协同工作来完成业务&#xff0c;就有了网络互连。 网络互连&#xff1a;将多…

除了Figma,再给你介绍10款好用的协同设计软件

组织结构越来越复杂&#xff0c;团队中的每个人都有独特的技能、经验和专业知识。我们怎样才能让团队更好地合作&#xff1f;在这种情况下&#xff0c;协同设计应运而生。 UI的未来是协同设计&#xff01;如果你想把握未来的设计趋势&#xff0c;不妨从使用高效的协同设计软件…

Docker的安装以及本地部署ILLA Builder

1.安装Docker&#xff0c;当前版本V4.18.0 。Docker引擎启动运行之后&#xff0c;效果如下图&#xff08;喜欢暗黑主题&#xff09; Docker启动可能出错&#xff0c;“Docker Desktop requires a newer WSL kernel version.” 如下图所示 解决方法&#xff0c;比较简单&#xf…

测试用例的基本要素和设计方法

作者&#xff1a;爱塔居 专栏&#xff1a;软件测试 作者简介&#xff1a;大三学生&#xff0c;希望同大家一起进步&#xff01; 文章简介&#xff1a;介绍写测试案例的功能需求测试和非功能需求测试和具体方法&#xff1a;判定表、正交表、等价类、边界值等 文章目录 目录 文章…

if条件语句

if条件语句 条件测试 test 测试表达式是否成立&#xff0c;若成立返回0&#xff0c;否则返回其他数值 格式1 &#xff1a;test 条件表达式&#xff1b;格式2 &#xff1a;[ 条件表达式 ] echo $?参数作用-d测试是否为目录 (Directory)-e测试目录或文件是否存在(Exist)-f测…

好物周刊#1:提示工程师养成指南

文章目录 &#x1f388; 项目ddruntiny-vuenetease-recent-profile &#x1f4bb; 软件BobScreenToGifSnipaste &#x1f578;️ 网站BrowserFramedocsmallDimmy.club &#x1f50c; 插件AdGuard[Global Speed: 视频速度控制](https://microsoftedge.microsoft.com/addons/deta…

强化学习-Double DQN、竞争网络结构和Rainbow(第4章)

来源书籍&#xff1a; TENSORFLOW REINFORCEMENT LEARNING QUICK START GUIDE 《TensorFlow强化学习快速入门指南-使用Python动手搭建自学习的智能体》 著者&#xff1a;[美]考希克巴拉克里希南&#xff08;Kaushik Balakrishnan&#xff09; 译者&#xff1a;赵卫东 出版…

【每日一题】leetcode21 - - 合并两个有序链表

文章目录 1.题目描述2.解题思路方法1&#xff1a;方法2&#xff1a; 1.题目描述 题目链接&#xff1a;力扣21&#xff0c;合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 2.解题思路 方法1&#xff1a;…

牛客网Verilog刷题——VL38

牛客网Verilog刷题——VL38 题目答案 题目 设计一个自动贩售机&#xff0c;输入货币有三种&#xff0c;为0.5/1/2元&#xff0c;饮料价格是1.5元&#xff0c;要求进行找零&#xff0c;找零只会支付0.5元。需要注意的是&#xff0c;投入的货币会自动经过边沿检测并输出一个在时钟…

【采坑专栏】【错误记录】起系统

doc说明 一级标题分大的&#xff0c;二级标题尽量加&#xff0c;三级标题是具体问题 语法 我的老毛病-易错的 多驱 复制粘贴导致前后一样 管脚约束还是直接选吧 多驱动 Vivado WARNING&#xff1a;Multi-driven net Q with xth driver pin 警告的原因和消除方法 出现这…

注意力机制:基于Yolov8的Triplet注意力模块,即插即用,效果优于cbam、se,涨点明显

论文&#xff1a;https://arxiv.org/pdf/2010.03045.pdf 本文提出了可以有效解决跨维度交互的triplet attention。相较于以往的注意力方法&#xff0c;主要有两个优点&#xff1a; 1.可以忽略的计算开销 2.强调了多维交互而不降低维度的重要性&#xff0c;因此消除了通道和权…

STM32F4_SRAM中调试代码

目录 1. 在RAM中调试代码 2. STM32的三种存储方式 3. STM32的启动方式 4. 实验过程 通过上一节的学习&#xff0c;我们已经了解了SRAM静态存储器&#xff1b; 1. 在RAM中调试代码 一般情况下&#xff0c;我们在MDK中编写工程应用后&#xff0c;调试时都是把程序下载到芯片…

Android类似微信聊天页面教程(Kotlin)四——数据本地化

前提条件 安装并配置好Android Studio Android Studio Electric Eel | 2022.1.1 Patch 2 Build #AI-221.6008.13.2211.9619390, built on February 17, 2023 Runtime version: 11.0.150-b2043.56-9505619 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11 …

Flink从入门到精通之-07处理函数

Flink从入门到精通之-07处理函数 之前所介绍的流处理 API&#xff0c;无论是基本的转换、聚合&#xff0c;还是更为复杂的窗口操作&#xff0c;其实都是基于 DataStream 进行转换的&#xff1b;所以可以统称为 DataStream API&#xff0c;这也是 Flink 编程的核心。而我们知道…

同样是测试,你年薪50W,我年薪10W,我哭了...

软件测试可以拿到年薪50万&#xff1f; 开什么玩笑&#xff1f; 我才月薪15K。 小伙伴看到标题是不是一开始的反应是这样的&#xff1f;是的话举一个小爪爪吧&#xff01; 那软件测试到底能不能拿到年薪50万呢&#xff1f; 没有吃过猪肉还没见过猪跑吗&#xff0c;你自己没…

【云原生-深入理解Kubernetes-1】容器的本质是进程

文章目录 &#x1f479; 关于作者一、为什么会出现容器&#xff1f;二、容器是什么&#xff1f;三、容器“边界”的实现手段3.1、进程如何运行的&#xff1f;3.2、Namespace 与 Docker 边界容器的本质是一个进程这是怎么做到的呢&#xff1f; 总结✊ 最后参考 &#x1f479; 关…

践行公益担当|人情如故,爱心依旧

爱心助学 情暖童心 随着改革开放&#xff0c;少数民族地区发生了翻天覆地的变化&#xff0c;城乡经济持续发展&#xff0c;人民生活水平日益提高。但对于很多居住在偏远山区的民族自然村&#xff0c;由于山区的地形限制&#xff0c;自然生存环境恶劣&#xff0c;交通及文化、教…

Android 项目必备(四十五)-->2023 年如何构建 Android 应用程序

Android 是什么 Android 是一种基于 Linux 内核并由 Google 开发的开源操作系统。它用于各种设备包括智能手机、平板电脑、电视和智能手表。 目前&#xff0c;Android 是世界上移动设备使用最多的操作系统; 根据 statcounter 的一份最近 12 个月的样本报告;Android 的市场份额…

C++ 编程笔记(本人出品,必属精品)

文章目录 Part.I IntroductionChap.I 快应用 Part.II C 基础Chap.I 一些待整理的知识点Chap.I 常用的库或类 Part.III 杂记Part.X Others WorkChap.I 大佬的总结Chap.II 大佬的轮子 Part.I Introduction 前言&#xff1a;C 用的人还是比较多的&#xff0c;主要是它比较快并且面…