数据结构——堆的实现

一、堆的定义

  堆是一种树形的数据结构,根据其特性又可分为大根堆小根堆(大顶堆和小顶堆)。堆的逻辑结构本质上是一颗完全二叉树。
大根堆:双亲结点(父结点)的权值大于等于其孩子结点的权值
小根堆:双亲结点(父结点)的权值小于等于其孩子结点的权值

二、堆的三要素

1.存储结构(真实的)

存储结构>逻辑结构<==>存储结构

2.逻辑结构(想象的)

堆的逻辑结构是一颗完全二叉树
逻辑结构
备注:建堆后可能不只有一种状态

3.运算集合(操作)

1.建堆算法
2.初始化
(1)给空间
(2)不给空间
3.判空
4.判满
5.堆长
6.打印堆
7.向上调整
8.向下调整
9.取堆顶元素
10.入堆
(1)初始化(给空间)
(2)初始化(不给空间)
11.出堆(删除堆顶元素)
12.销毁堆

三、堆的实现

1.heap.h

#define _CRT_SECURE_NO_WARNINGS

#pragma warning(disable:6031)
#pragma once

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

//方便修改数据类型
typedef int HPElemType;

//定义堆的结点
typedef struct HPNode
{
	HPElemType* arr;//数据域
	int size;
	int capacity;
}HP;

void CreateHeap(HPElemType* pa, int n);//建堆算法

void HPInit1(HP* php);//初始化 给空间

void HPInit2(HP* php);//初始化 不给空间

bool IsEmpty(HP* php);//判空

bool IsFull(HP* php);//判满

int HPSize(HP* php);//堆元素的个数

void PrintHeap(HP* hp);//打印堆中的元素与堆的大小

void AdjustUp(HPElemType* pa,int child);//向上调整

void AdjustDown(HPElemType* pa, int n, int parent);//向下调整

HPElemType GetHeapTopElement(HP* php);//取堆顶元素

void HPPush1(HP* php, HPElemType x);//入堆 初始化1
void HPPush2(HP* php, HPElemType x);//入堆 初始化2

void HPPop(HP* php);//出堆 删除堆顶元素

void HPDestroy(HP* php);//销毁

2.heap.c

#include "heap.h"

//建堆算法(将一个数组构造成堆)
void CreateHeap(HPElemType* pa, int n)
{
	assert(pa);

	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
		AdjustDown(pa, n, i);
}

//初始化 给空间
void HPInit1(HP* php)
{
	assert(php);

	php->arr = (HPElemType*)malloc(sizeof(HPElemType) * 4);
	if (php->arr == NULL)
	{
		perror("malloc fali!");
		return;
	}

	php->capacity = 4;
	php->size = 0;
}

//初始化 不给空间
void HPInit2(HP* php)
{
	assert(php);

	php->arr = NULL;
	php->capacity = php->size = 0;
}

//判空
bool IsEmpty(HP* php)
{
	assert(php);

	if (php->size == 0)
		return true;

	return false;
}

//判满
bool IsFull(HP* php)
{
	assert(php);

	if (php->size == php->capacity && php->capacity != 0)
		return true;

	return false;
}

//堆元素的个数
int HPSize(HP* php)
{
	assert(php);

	return php->size;
}

//打印堆中的元素与堆的大小
void PrintHeap(HP* php)
{
	assert(php);

	for (int i = 0; i < HPSize(php); i++)
		printf("%d ", php->arr[i]);

	printf("\n");
	printf("该堆的元素个数为:%d\n", HPSize(php));
}

//交换数据
void Swap(HPElemType* p1,HPElemType* p2)
{
	HPElemType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//向上调整
void AdjustUp(HPElemType* pa,int child)
{
	assert(pa);

	int parent = (child - 1) / 2;

	while (child > 0)
	{
		if (pa[child] > pa[parent])
		{
			Swap(&pa[child], &pa[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

//向下调整
void AdjustDown(HPElemType* pa,int n,int parent)
{
	assert(pa);

	int child = parent * 2 + 1;

	/*while (parent < n / 2)*/
	while (child < n)
	{
		if (child + 1 < n && pa[child + 1] > pa[child])
			child++;

		if (pa[child] > pa[parent])
		{
			Swap(&pa[child], &pa[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//取堆顶元素
HPElemType GetHeapTopElement(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->arr[0];
}

//插入 调用初始化1函数
void HPPush1(HP* php,HPElemType x)
{
	assert(php);

	//满了就扩容(realloc)
	if(IsFull(php))
	{
		HPElemType* tmp = (HPElemType*)realloc(php->arr, sizeof(HPElemType) * php->capacity * 2);
		if (tmp == NULL)
			return;

		php->arr = tmp;
		php->capacity *= 2;
	}

	php->arr[php->size++] = x;

	AdjustUp(php->arr, php->size - 1);
}

//插入 调用初始化2函数
void HPPush2(HP* php, HPElemType x)
{
	assert(php);

	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;

		HPElemType* tmp = realloc(php->arr, sizeof(HPElemType) * newcapacity);
		if (tmp == NULL)
			return;

		php->arr = tmp;
		php->capacity = newcapacity;
	}

	php->arr[php->size++] = x;

	AdjustUp(php->arr, php->size - 1);
}

//删除堆顶元素
void HPPop(HP* php)
{
	assert(php);

	Swap(&php->arr[php->size - 1], &php->arr[0]);
	php->size--;

	AdjustDown(php->arr, php->size, 0);
}

//销毁堆
void HPDestroy(HP* php)
{
	assert(php);

	free(php->arr);
	php->arr = NULL;

	php->capacity = php->size = 0;
}

3.main.c

#include "heap.h"

void TestHP1()
{
	printf("TestHP1:\n");
	//创建结构体变量
	HP hp;

	HPInit1(&hp);

	HPPush1(&hp, 4);
	HPPush1(&hp, 5);
	HPPush1(&hp, 8);
	HPPush1(&hp, 2);
	HPPush1(&hp, 4);
	HPPush1(&hp, 0);
	HPPush1(&hp, 1);
	HPPush1(&hp, 5);
	HPPush1(&hp, 6);
	PrintHeap(&hp);

	HPPop(&hp);
	HPPop(&hp);
	HPPop(&hp);
	HPPop(&hp);
	PrintHeap(&hp);

	HPDestroy(&hp);
	printf("\n");
}

void TestHP2()
{
	printf("TestHP2:\n");
	//创建结构体变量
	HP hp;

	HPInit2(&hp);

	HPPush2(&hp, 4);
	HPPush2(&hp, 5);
	HPPush2(&hp, 8);
	HPPush2(&hp, 2);
	HPPush2(&hp, 4);
	HPPush2(&hp, 0);
	HPPush2(&hp, 1);
	HPPush2(&hp, 5);
	HPPush2(&hp, 6);
	PrintHeap(&hp);

	//伪排序
	while (!IsEmpty(&hp))
	{
		printf("%d ", GetHeapTopElement(&hp));
		HPPop(&hp);
	}
	printf("\n");

	HPDestroy(&hp);
	printf("\n");
}

void TestHP3()
{
	printf("TestHP3:\n");
	HPElemType arr[] = { 4,5,8,2,4,0,1,5,6 };
	int len = sizeof(arr) / sizeof(HPElemType);
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");

	//建堆算法
	CreateHeap(arr, len);
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");

}

int main()
{
	TestHP1();

	TestHP2();

	TestHP3();

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值