typedef int HPDataType;
typedef struct Heap
{
HPDataType* _a;
int _size;
int _capacity;
}Heap;
对传入的数据进行建堆,假设要查找前几个小的数据。
应该建大堆,然后依次把堆顶数据和最后一个数据交换,
//交换
void Swap(HPDataType* p1, HPDataType* p2)
{
HPDataType tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//向下调整
void ADjustDown(HPDataType* a, int n,int root)
{
int parent = root; //把堆顶的位置下标给父亲
int child = parent * 2 + 1; //找到孩子的位置
while (child < n) //孩子的下标小于堆里的数据个数就继续
{
//找出左右孩子小的哪一个
if ((child +1) < n &&a[child + 1] < a[child])//防治下标越界
{
++child;
}
//孩子小于父亲就交换
if (a[child] < a[parent])
{
Swap(&a[child], &a[parent]);
parent = child; //继续迭代
child = parent * 2 + 1;
}
else
{
break;//不满足就退出
}
}
}
//初始化
void HeapInit(Heap* php, HPDataType* a, int n)
{
php->_a = (HPDataType*)malloc(sizeof(HPDataType) * n);//开辟一块空间
memcpy(php->_a, a, sizeof(HPDataType) * n);//拷贝原空间的数据到开辟空间里
php->_size = n;//更新数据个数
php->_capacity = n;//可用的数组数据
//构建堆
for (int i = (n - 1 - 1) / 2; i > 0; --i)//往叶子节点开始调整
{
ADjustDown(php->_a, php->_size, i);
}
}
入了数据后要使堆满足之前的条件,使其还是小堆。(这里我创建的是小堆)
//交换
void Swap(HPDataType* p1, HPDataType* p2)
{
HPDataType tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//向上调整;
void AdjustUP(HPDataType* a, int n, int child)
{
int parent = (child - 1) / 2; //找到父亲的位置下标
while (child > 0) //孩子的下标大于0就循环,到0了就是堆顶的数据,就不用调整了
{
if (a[child] < a[parent]) //孩子小于父亲就向上调整
{
Swap(&a[child], &a[parent]);
child = parent;//更新child的位置下标
parent = (child - 1) / 2;//继续查找父亲的位置下标
}
else
{
break; //不满足条件就退出
}
}
}
//往推入数据
void HeapPush(Heap* php, HPDataType x)
{
assert(php);
//空间不够就扩容
if (php->_size == php->_capacity)
{
php->_capacity *= 2;//扩容2倍
//动态开辟
HPDataType* tmp = (HPDataType *)realloc(php->_a, sizeof(HPDataType)*php->_capacity);
php->_a = tmp;//把开辟的空间更新
}
php->_a[php->_size++] = x;//把数据给到最后一个叶子节点
AdjustUP(php->_a, php->_size, php->_size - 1);//向上调整,使堆满足小堆
}
//弹数据
void HeapPop(Heap* php)
{
assert(php);
assert(php->_size > 0);//数据个数必须为有效个数
//从堆顶删除数据,把堆顶数据和最后一个数据交换位置,然后删除最后一个节点
Swap(&php[0], &php->_a[php->_size - 1]);
php->_size--;//下标--
ADjustDown(php->_a, php->_size, 0);//向下调整使数据,满足小堆条件
}
//堆顶数据
HPDataType HeapTop(Heap* php)
{
assert(php);
assert(php->_size > 0);//数据个数为有效个
return php->_a[0];//堆顶的数据就是第一个数据
}
//销毁
void HeapDestory(Heap* php)
{
assert(php);
free(php->_a);//释放创建的空间
php->_a = NULL;
php->_size = php->_capacity = 0;
}
#pragma once
#include
#include
#include
#include
typedef int HPDataType;
typedef struct Heap
{
HPDataType* _a;
int _size;
int _capacity;
}Heap;
//向下调整
void ADjustDown(HPDataType* a, int n, int root);
//初始化
void HeapInit( Heap* php,HPDataType *a,int n);
//销毁
void HeapDestory( Heap* php);
//往推入数据
void HeapPush(Heap* php, HPDataType x);
//删除堆数据
void HeapPop(Heap* php);
//堆顶数据
HPDataType HeapTop(Heap* php);
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
//交换
void Swap(HPDataType* p1, HPDataType* p2)
{
HPDataType tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//向上调整;
void AdjustUP(HPDataType* a, int n, int child)
{
int parent = (child - 1) / 2; //找到父亲的位置下标
while (child > 0) //孩子的下标大于0就循环,到0了就是堆顶的数据,就不用调整了
{
if (a[child] < a[parent]) //孩子小于父亲就向上调整
{
Swap(&a[child], &a[parent]);
child = parent;//更新child的位置下标
parent = (child - 1) / 2;//继续查找父亲的位置下标
}
else
{
break; //不满足条件就退出
}
}
}
//向下调整
void ADjustDown(HPDataType* a, int n,int root)
{
int parent = root; //把堆顶的位置下标给父亲
int child = parent * 2 + 1; //找到孩子的位置
while (child < n) //孩子的下标小于堆里的数据个数就继续
{
//找出左右孩子小的哪一个
if ((child +1) < n &&a[child + 1] < a[child])//防治下标越界
{
++child;
}
//孩子小于父亲就交换
if (a[child] < a[parent])
{
Swap(&a[child], &a[parent]);
parent = child; //继续迭代
child = parent * 2 + 1;
}
else
{
break;//不满足就退出
}
}
}
//初始化
void HeapInit(Heap* php, HPDataType* a, int n)
{
php->_a = (HPDataType*)malloc(sizeof(HPDataType) * n);//开辟一块空间
memcpy(php->_a, a, sizeof(HPDataType) * n);//拷贝原空间的数据到开辟空间里
php->_size = n;//更新数据个数
php->_capacity = n;//可用的数组数据
//构建堆
for (int i = (n - 1 - 1) / 2; i > 0; --i)//往叶子节点开始调整
{
ADjustDown(php->_a, php->_size, i);
}
}
//销毁
void HeapDestory(Heap* php)
{
assert(php);
free(php->_a);//释放创建的空间
php->_a = NULL;
php->_size = php->_capacity = 0;
}
//往推入数据
void HeapPush(Heap* php, HPDataType x)
{
assert(php);
//空间不够就扩容
if (php->_size == php->_capacity)
{
php->_capacity *= 2;//扩容2倍
//动态开辟
HPDataType* tmp = (HPDataType *)realloc(php->_a, sizeof(HPDataType)*php->_capacity);
php->_a = tmp;//把开辟的空间更新
}
php->_a[php->_size++] = x;//把数据给到最后一个叶子节点
AdjustUP(php->_a, php->_size, php->_size - 1);//向上调整,使堆满足小堆
}
//弹数据
void HeapPop(Heap* php)
{
assert(php);
assert(php->_size > 0);//数据个数必须为有效个数
//从堆顶删除数据,把堆顶数据和最后一个数据交换位置,然后删除最后一个节点
Swap(&php[0], &php->_a[php->_size - 1]);
php->_size--;//下标--
ADjustDown(php->_a, php->_size, 0);//向下调整使数据,满足小堆条件
}
//堆顶数据
HPDataType HeapTop(Heap* php)
{
assert(php);
assert(php->_size > 0);//数据个数为有效个
return php->_a[0];//堆顶的数据就是第一个数据
}
#include"Heap.h"
void HeapSort(int* a, int n)
{
//建堆
//for(int i = n - 1; i >= 0; --i) 从最后一个下标开始找
//时间复杂度
//假设有N个节点,树高度LogN
for (int i = (n - 1-1)/2 ; i >= 0; --i)//最后一个叶子节点的位置
{
ADjustDown(a, n, i);//向下调整
}
int end = n - 1;//最后一个叶子节点位置
while (end)//到顶了就停止
{
Swap(&a[0], &a[end]);//把堆顶和最后一个数据交换
ADjustDown(a, end, 0);//继续调整堆中数据,直到满足小堆
--end;//下标--
}
}
int main()
{
int arr[] = {27,15,19,18,28,34,65,49,25,37};//创建数组
Heap hp;//创建一个堆
HeapInit(&hp, arr, sizeof(arr) / sizeof(HPDataType));//拷贝原数据
HeapPush(&hp, 14);//往堆插入数据
HeapPush(&hp, 9);
HeapPush(&hp, 5);
HeapDestory(&hp);//销毁
return 0;
}