数据结构初阶 堆(一)

一. 堆的概念和性质

我们在上一篇博客介绍存储二叉树的两种方式

分别是顺序结构和链式结构

数据结构初阶 初识二叉树-CSDN博客

1. 堆的概念

这里注意!!! 这里说的堆和操作系统里面的堆没有半点关系!!!

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

上面这个就是官方的解释了

但是要是我们用通俗的话来说

就是这样子的

大堆 就是所有的父节点都大于等于子节点的堆

小堆 就是所有的子节点都小于等于父节点的堆

如图

2. 堆的性质

  1. 堆总是一棵完全的二叉树

  2. 堆中某个节点的值总是不大于或者不小于其父节点的值

3. 小题目练练手

1.下列关键字序列为堆的是:()

A 100,60,70,50,32,65

B 60,70,65,50,32,100

C 65,100,70,32,50,60

D 70,65,100,32,50,60

E 32,50,100,70,65,60

F 50,100,70,65,60,32

我们首先来看A

很明显 满足大堆的定义

所以该题选A

我们再来看看B是不是错的

很明显是错的

所以更加确定了答案是A

二. 代码实现以及堆的部分接口函数

1. 结构体代码

结构体代码表示如下

复制代码
typedef int HPDateType;

typedef struct Heap
{
	HPDateType* a;
	int size;
	int capacity;
}HP;

2. 初始化以及销毁

这两段代码很简单 这里就连起来写了

复制代码
void HeapInit(HP* php)
{
	assert(php);
	php->a = (HPDateType*)malloc(sizeof(HPDateType) * 4);
	if (php->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	php->size =0;
	php->capacity = 4;
}
void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php = NULL;
	php->size = 0;
	php->capacity = 0;
}

两段代码表示如上

3. 增加数据 (大堆为例)

复制代码
void HeapPush(HP* php, HPDateType x)

我们这里增加数据要先考虑一点

储存数据的空间够不够

如果不够的话我们就要扩容空间了

这一段代码已经讲过很多次了

我就不讲解了

判断代码如下

复制代码
	assert(php);
	if (php->size == php->capacity)
	{
		HPDateType* tmp = (HPDateType*)realloc(php->a,sizeof(HPDateType) * php->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity *= 2;
	}
	php->a[php->size] = x;
	php->size++;

当我们这里插入一个75的时候 这里明显是错误的啊 怎么办呢?

这个时候我们就需要将它跟它的父亲比较 是否大于它的父亲

如果不大于就填入

如果小于就交换它和它的父亲

知道孩子等于0为止

下面开始写代码

我们用一个函数来写 防止要复用

复制代码
void Swap(HPDateType* p1, HPDateType* p2)
{
	HPDateType x = *p1;
	*p1 = *p2;
	*p2 = x;
}
//除child这个位置,前面数据构成堆
//向上调整
void AdJustUp(HPDateType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			//更新父亲的位置
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HeapPush(HP* php, HPDateType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		HPDateType* tmp = (HPDateType*)realloc(php->a,sizeof(HPDateType) * php->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity *= 2;
	}
	php->a[php->size] = x;
	php->size++;
	AdJustUp(php->a, php->size - 1);
}

整体代码表示如上

相关推荐
多加点辣也没关系22 分钟前
数据结构与算法|第十七章:贪心算法
数据结构·算法·贪心算法
多加点辣也没关系23 分钟前
数据结构与算法|第十四章:排序算法(上)— 比较类排序
数据结构·算法·排序算法
北顾笙9801 小时前
day42-数据结构力扣
数据结构
风筝在晴天搁浅1 小时前
阿里淘天/京东 CodeTop LeetCode103.二叉树的锯齿形层序遍历
数据结构
郝学胜-神的一滴1 小时前
干货版《算法导论》03:动态数组 × 链表的极致平衡艺术
java·数据结构·c++·python·算法·链表
图码2 小时前
最大子数组和问题:从暴力到Kadane算法的优雅蜕变
数据结构·算法·动态规划·柔性数组
庞轩px2 小时前
第一篇:Redis数据结构底层——String、List、Hash、Set、ZSet各自用什么实现的?
数据结构·redis·list·set·hash·string·zset
qq_296553272 小时前
[特殊字符] 数组中的递增三元组:O(n) 时间高效查找,面试必考!
数据结构·算法·面试·职场和发展·组合模式·柔性数组
今儿敲了吗3 小时前
链表篇(一)——合并两个有序链表
数据结构·笔记·算法·链表
y = xⁿ3 小时前
20天速通LeetCodeday11:二叉树进阶
数据结构·算法