【数据结构】堆的实现

目录

一、堆的概念

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;
}
相关推荐
对方正在长头发丿2 分钟前
LETTERS(DFS)
c++·笔记·算法·深度优先·图论
Qian_ShouYi3 分钟前
MATLAB 代码学习
学习·算法·matlab
lovebugs1 小时前
K8s面试第一篇:初识Kubernetes——核心概念与组件详解
后端·算法·面试
HelloDam1 小时前
基于元素小组的归并排序算法
后端·算法·排序算法
HelloDam1 小时前
基于连贯性算法的多边形扫描线生成(适用于凸多边形和凹多边形)【原理+java实现】
算法
逸狼2 小时前
【Java 优选算法】二分算法(下)
数据结构
uhakadotcom2 小时前
Apache Airflow入门指南:数据管道的强大工具
算法·面试·github
跳跳糖炒酸奶3 小时前
第四章、Isaacsim在GUI中构建机器人(2):组装一个简单的机器人
人工智能·python·算法·ubuntu·机器人
绵绵细雨中的乡音3 小时前
动态规划-第六篇
算法·动态规划
程序员黄同学3 小时前
动态规划,如何应用动态规划解决实际问题?
算法·动态规划