【数据结构】堆的实现

目录

一、堆的概念

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;
}
相关推荐
明朝百晓生5 分钟前
【强化学习】【1】【PyTorch】【强化学习简介优化框架】
算法
loser~曹11 分钟前
基于快速排序解决 leetcode hot215 查找数组中第k大的数字
数据结构·算法·leetcode
Dream it possible!16 分钟前
LeetCode 热题 100_打家劫舍(83_198_中等_C++)(动态规划)
c++·算法·leetcode·动态规划
zhouziyi070122 分钟前
【蓝桥杯14天冲刺课题单】Day 8
c++·算法·蓝桥杯
SylviaW0826 分钟前
python-leetcode 62.搜索插入位置
数据结构·算法·leetcode
丶Darling.27 分钟前
26考研 | 王道 | 数据结构 | 第四章 串
数据结构·考研·kmp
北极象1 小时前
用C实现一个最简单的正则表达式引擎
c语言·正则表达式·php
舔甜歌姬的EGUMI LEGACY2 小时前
【算法day28】解数独——编写一个程序,通过填充空格来解决数独问题
算法
深圳厨神2 小时前
浅谈数据结构
数据结构
JCBP_2 小时前
数据结构4
运维·c语言·数据结构·vscode