堆(数据结构)

堆的概念与结构

堆的底层逻辑是一个完全二叉树(或满二叉树)。

堆的分类

大根堆和小根堆

大根堆

所谓大根堆就是每一个父节点都要大于等于子结点

小根堆

所谓小根堆就是每一个父节点都要小于等于子结点

堆的实现

实现接口

Heap.h


#pragma once
//堆实现  底层逻辑是数组
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int HPDataType;
typedef struct Heap {
	HPDataType* a;
	int size;
	int capacity;
}Hp;
//初始化堆
void HpInit(Hp* php);
//向上调整
void AdjustUp(HPDataType* a, int child);
//向下调整
void AdjustDown(HPDataType* a, int size, int parent);
//往堆里插入数据
void HpPush(Hp* php,HPDataType x);
//删除数据
void HpPop(Hp* php);
//获取堆首元素
HPDataType HpTop(Hp* php);
//堆中元素个数
int Hpsize(Hp* php);
//判空
bool HpEmpty(Hp* php);
//销毁堆
void HpDestory(Hp* php);

实现函数

Heap.c

#define _CRT_SECURE_NO_WARNINGS 1
//大堆小堆只需要改变调整关系即可
#include"Heap.h"
//初始化堆
void HpInit(Hp* php) {
	assert(php);
	php->a = NULL;
	php->capacity = 0;
	php->size = 0;
}
//交换孩子和父亲的位置
void Swap(HPDataType* child,HPDataType* parents) {
	HPDataType tem = *child;
	*child = *parents;
	*parents = tem;
}
//向上调整
void AdjustUp(HPDataType* a, int child) {
	int parents = (child - 1) / 2;
	while (child > 0) {
		if (a[child] > a[parents]) {
			Swap(&a[child], &a[parents]);
			child = parents;
			parents = (child - 1) / 2;
		}
		else {
			break;
		}
	}
}
//向下调整
void AdjustDown(HPDataType* a,int size, int parent) {
	int child = parent * 2 + 1;
	while(child<size){
		if (child+1<size && a[child + 1] > a[child]) {
			child++;
		}
		if (a[parent] < a[child]) {
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else {
			break;
		}
	}
}
//往堆里插入数据
void HpPush(Hp* php, HPDataType x) {
	assert(php);
	//先判断是否还有数据
	if (php->size == php->capacity) {
		//开空间
		int Newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HPDataType* tem = (HPDataType*)realloc(php->a,sizeof(HPDataType) * Newcapacity);
		if (tem == NULL) {
			perror("realoc");
			exit(-1);
		}
		php->capacity = Newcapacity;
		php->a = tem;
	}
	php->a[php->size] = x;
	php->size++;
	//在此之前已经数据插入到数组中
	//然后在比较大小
	AdjustUp(php->a, php->size - 1);
}
//删除数据  默认删除堆顶数据
void HpPop(Hp* php) {
	assert(php);
	assert(php->size>0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	AdjustDown(php->a, php->size, 0);
}
//获取堆首元素
HPDataType HpTop(Hp* php) {
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}
//堆中元素个数
int Hpsize(Hp* php) {
	assert(php);
	assert(php->size > 0);
	return php->size;
}
//判空
bool HpEmpty(Hp* php) {
	assert(php);
	return php->size == 0;
}
//销毁堆
void HpDestory(Hp* php) {
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = php->size= 0;
}

测试函数

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void test01() {
	Hp hp;
	HpInit(&hp);
	int a[] = { 2,4,6,7,1,23,434,5,9,20,1,2,4,3 };
	for (int i = 0; i < sizeof(a) / sizeof(int); i++) {
		HpPush(&hp, a[i]);
	}
	int k = 0;
	while (!HpEmpty(&hp)) {
		//printf("%d ", HpTop(&hp));
		//把取到的数据全部放入a数组中
		a[k++] = HpTop(&hp);
		HpPop(&hp);
	}
	for (int i = 0; i < sizeof(a) / sizeof(int); i++) {
		printf("%d ", a[i]);
	}
	HpDestory(&hp);
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值