【数据结构】堆的实现

目录

一、堆的概念

1.概念:

2.性质

二.堆的实现

[1.用数组定义堆结构struct Heap](#1.用数组定义堆结构struct Heap)

2.交换两个数swap函数

3.向下调整算法AdjustDown函数

4.向上调整算法AdjustUp函数

5.初始化堆HeapInit函数

6.销毁堆HeapDestory函数

7.堆的插入HeapPush函数

8.堆的删除HeapPop函数

[9.取堆顶数据 HeapTop函数](#9.取堆顶数据 HeapTop函数)

[10.取堆数据个数 HeapSize函数](#10.取堆数据个数 HeapSize函数)

[11.堆判空 HeapEmpty函数](#11.堆判空 HeapEmpty函数)


一、堆的概念

1.概念:

堆是将一个完全二叉树以顺序存储方式存储在数组中的一个数据结构,这颗完全二叉树需满足父节点的值大于等于(小于等于)孩子节点的值。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的逻辑结构为完全二叉树,物理结构为一维数组

2.性质

(1)堆中某个节点的值总是不大于或不小于其父节点的值;(整个树所有结点需保持同一个规律,。要大于等于,都大于等于。反之同理)

(2)堆逻辑总是一棵完全二叉树

注:

一个升序(降序)的数组一定是堆

但堆的数组不一定就是升序(降序)

二.堆的实现

1.用数组定义堆结构struct Heap
cpp 复制代码
typedef struct Heap
{
	HPDataType* _a;
	int _size;
	int _capacity;
}Heap;
2.交换两个数swap函数
cpp 复制代码
void swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
3.向下调整算法AdjustDown函数

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整 成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

cpp 复制代码
int array[] = {27,15,19,18,28,34,65,49,25,37};

向下调整过程如图:

cpp 复制代码
//小堆
void AdjustDown(Heap* hp, int parent)
{
	int child = parent * 2 + 1;
	while (child<hp->_size)
	{
		//判断是否存在右孩子,且值小于左孩子
		if (child + 1 < hp->_size && hp->_a[child + 1] < hp->_a[child])
		{
			child++;
		}

		//判断parent节点和child节点的大小
		if (hp->_a[child] < hp->_a[parent])
		{
			swap(&(hp->_a[child]), &(hp->_a[parent]));
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
4.向上调整算法AdjustUp函数

前提:插入前逻辑上为堆(大堆or小堆)

cpp 复制代码
//按小堆检查
void AdjustUp(Heap* hp, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (hp->_a[parent] > hp->_a[child])
		{
			int tmp = hp->_a[child];
			hp->_a[child] = hp->_a[parent];
			hp->_a[parent] = tmp;
		}
		else
		{
			break;
		}
		child = parent;
		parent = (child - 1) / 2;
	}
}
5.初始化堆HeapInit函数
cpp 复制代码
//初始化堆
void HeapInit(Heap* hp)
{
	assert(hp);
	hp->_a = NULL;
	hp->_capacity = hp->_size = 0;
}
6.销毁堆HeapDestory函数
cpp 复制代码
// 堆的销毁
void HeapDestory(Heap* hp)
{
	free(hp->_a);
	free(hp);
	hp = NULL;
}
7.堆的插入HeapPush函数
cpp 复制代码
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);
	//判断堆是否已经满
	if (hp->_size == hp->_capacity)
	{
		int newcapacity = hp->_capacity == 0 ? 4 : 2 * hp->_capacity;
		int* tmp = (int*)realloc(hp->_a,sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		hp->_a = tmp;
		hp->_capacity = newcapacity;
	}
	hp->_a[hp->_size] = x;
	AdjustUp(hp, hp->_size);
	hp->_size++;
}
8.堆的删除HeapPop函数
cpp 复制代码
//默认为删除堆顶
//为了不影响整体结构,将堆顶元素与堆尾交换后,删除。之后需向下调整堆,维持堆的性质
void HeapPop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	//交换
	swap(&(hp->_a[0]), &(hp->_a[hp->_size - 1]));

	//删除
	hp->_size--;

	//向下调整
	AdjustDown(hp, 0);
}
9.取堆顶数据 HeapTop函数

因为物理结构是一个数组,所以取下标为0的数就是堆顶数据。

cpp 复制代码
// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
	return hp->_a[0];
}
 
10.取堆数据个数 HeapSize函数

直接输出size的大小。

cpp 复制代码
// 堆的数据个数
int HeapSize(Heap* hp)
{
	return hp->_size;
}
11.堆判空 HeapEmpty函数

直接判断堆数据size的大小是否为0。

cpp 复制代码
// 堆的判空
int HeapEmpty(Heap* hp)
{
	return hp->_size == 0;
}
相关推荐
passer__jw76725 分钟前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
Ocean☾31 分钟前
前端基础-html-注册界面
前端·算法·html
顶呱呱程序39 分钟前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
TeYiToKu1 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
互联网打工人no11 小时前
每日一题——第一百二十四题
c语言
爱吃生蚝的于勒1 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~1 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
洋2401 小时前
C语言常用标准库函数
c语言·开发语言
王哈哈^_^1 小时前
【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·pyqt
星沁城2 小时前
240. 搜索二维矩阵 II
java·线性代数·算法·leetcode·矩阵