一、堆的定义
堆是一种树形的数据结构,根据其特性又可分为大根堆和小根堆(大顶堆和小顶堆)。堆的逻辑结构本质上是一颗完全二叉树。
大根堆:双亲结点(父结点)的权值大于等于其孩子结点的权值
小根堆:双亲结点(父结点)的权值小于等于其孩子结点的权值
二、堆的三要素
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;
}