1.将待排序的序列视为一个完全二叉树。
2.从最后一个非叶子节点开始,向前逐个对每个节点进行调整。最后一个非叶子节点的位置可以通过序列长度计算得出,设序列长度为n,则最后一个非叶子节点的位置是n/2 - 1(假定序列的起始索引为0)。
3.对于每个非叶子节点,通过与其子节点比较并进行交换(如果需要),确保该节点的值大于或等于其子节点的值,从而满足最大堆的性质。
堆的初始化(二级指针)
void InitHeap(heap**pphp, HDataType *original, int size)//堆的二级地址、数组、数组的大小
{
//申请内存
int newcapacity=size > MAX_SIZE ? size : MAX_SIZE;
(*pphp)->arr = (HDataType*)malloc(sizeof(HDataType) * size);
if ((*pphp)->arr == NULL)
{
printf("Malloc Fail");
exit(-1);
}
//初始化
else
{
(*pphp)->capacity = newcapacity;
(*pphp)->size = 0;
memcpy((*pphp)->arr , original, size * sizeof(original[0]));
(*pphp)->size = size;
}
}
堆的创建
void BuildHeap(heap hp)
{
int i = 0;
for (i = hp.size / 2 - 1; i >= 0; i--)
{
AdjustDoneHeap(hp, i);//非子叶结点
}
}
void AdjustDoneHeap(heap hp, int index)
{
//自下而上 下滤
int parent;
int child=index;
for (parent = index; parent * 2 + 1 < hp.size; parent = child)
{
child = parent * 2 + 1;//孩子结点(左孩子)
if ((child + 1 < hp.size) && (hp.arr[child] < hp.arr[child + 1]))//判断右孩子是否存在
{
child++;//右孩子>左孩子,child为右孩子
}
if (hp.arr[child] <= hp.arr[parent])//parent<child
{
break;
}
else
{
HDataType swap;
swap = hp.arr[child];
hp.arr[child] = hp.arr[parent];
hp.arr[parent] = swap;
}
}
}
插入元素(二级指针)
插入新元素:将新元素添加到堆的末尾(在数组实现中,通常是将新元素添加到数组的末尾)。
调整堆序:从新插入的元素开始,与其父节点进行比较。如果新插入的元素大于其父节点,则将它们交换位置。继续这个过程,直到新元素小于或等于其父节点,或者新元素已经成为根节点。这个过程称为“上浮”或“上滤”。
bool InsertHeap(heap**pphp, int a)
{
if ((*pphp)->size == (*pphp)->capacity )
{
printf("内存耗尽,放入失败");
exit(-1);
}
else
{
int value = (*pphp)->size ;//记录插入元素在数组中的位置
(*pphp)->arr[(*pphp)->size++] = a;
heap hp = *(*pphp);
AdjustUp(hp,value);
return true;
}
}
void AdjustUp(heap hp, int value)
{
if (value > hp.size||value<0)
{
return;
}
else
{
while(value > 0)
{
int parent = (value - 1) / 2;
if (parent >= 0)
{
if (hp.arr[parent] < hp.arr[value])
{
HDataType c;
c = hp.arr[parent];
hp.arr[parent] = hp.arr[value];
hp.arr[value] = c;
value = parent;
}
else
{
break;
}
}
else
{
break;
}
}
}
/*for (int i = 0; i < hp.size; i++)
{
printf("%d ", hp.arr[i]);
}
printf("\n");*/
}
取出元素
1.将堆顶元素(通常是数组的第一个元素)取出,将最后一个元素放入第一个元素。
2.删除最后一个元素。
3.从新的堆顶元素开始,进行堆的调整。这通常是通过一系列的比较和交换操作,使得堆的性质(父节点的值大于或等于其子节点的值)得以保持。
HDataType PopHeap(heap**pphp)
{
assert((*pphp)->size > 0);
HDataType a = (*pphp)->arr[0];
(*pphp)->arr[0] = (*pphp)->arr[--(*pphp)->size];
heap hp = *(*pphp);
AdjustDoneHeap(hp, 0);
return a;
}
源代码
#define MAX_SIZE 128
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<assert.h>
typedef int HDataType;
typedef struct heap_
{
HDataType* arr;
int size;
int capacity;
}heap;
void AdjustDoneHeap(heap hp, int index);
void AdjustUp(heap hp, int value);
void BuildHeap(heap hp)
{
int i = 0;
for (i = hp.size / 2 - 1; i >= 0; i--)
{
AdjustDoneHeap(hp, i);//非子叶结点
}
}
void AdjustDoneHeap(heap hp, int index)
{
//自下而上 下滤
int parent;
int child=index;
for (parent = index; parent * 2 + 1 < hp.size; parent = child)
{
child = parent * 2 + 1;//孩子结点(左孩子)
if ((child + 1 < hp.size) && (hp.arr[child] < hp.arr[child + 1]))//判断右孩子是否存在
{
child++;//右孩子>左孩子,child为右孩子
}
if (hp.arr[child] <= hp.arr[parent])//parent<child
{
break;
}
else
{
HDataType swap;
swap = hp.arr[child];
hp.arr[child] = hp.arr[parent];
hp.arr[parent] = swap;
}
}
}
void InitHeap(heap**pphp, HDataType *original, int size)//堆的二级地址、数组、数组的大小
{
//申请内存
int newcapacity=size > MAX_SIZE ? size : MAX_SIZE;
(*pphp)->arr = (HDataType*)malloc(sizeof(HDataType) * size);
if ((*pphp)->arr == NULL)
{
printf("Malloc Fail");
exit(-1);
}
//初始化
else
{
(*pphp)->capacity = newcapacity;
(*pphp)->size = 0;
memcpy((*pphp)->arr , original, size * sizeof(original[0]));
(*pphp)->size = size;
}
}
bool InsertHeap(heap**pphp, int a)
{
if ((*pphp)->size == (*pphp)->capacity )
{
printf("内存耗尽,放入失败");
exit(-1);
}
else
{
int value = (*pphp)->size ;//记录插入元素在数组中的位置
(*pphp)->arr[(*pphp)->size++] = a;
heap hp = *(*pphp);
AdjustUp(hp,value);
return true;
}
}
void AdjustUp(heap hp, int value)
{
if (value > hp.size||value<0)
{
return;
}
else
{
while(value > 0)
{
int parent = (value - 1) / 2;
if (parent >= 0)
{
if (hp.arr[parent] < hp.arr[value])
{
HDataType c;
c = hp.arr[parent];
hp.arr[parent] = hp.arr[value];
hp.arr[value] = c;
value = parent;
}
else
{
break;
}
}
else
{
break;
}
}
}
}
HDataType PopHeap(heap**pphp)
{
assert((*pphp)->size > 0);
HDataType a = (*pphp)->arr[0];
(*pphp)->arr[0] = (*pphp)->arr[--(*pphp)->size];
heap hp = *(*pphp);
AdjustDoneHeap(hp, 0);
return a;
}
int main()
{
int i = 0;
heap hp = {NULL,0,0};
heap* php = &hp;
HDataType original[] = {6,9,1,5,8,4,7};
InitHeap(&php, original, sizeof(original) / sizeof(original[0]));
BuildHeap(hp);
//InsertHeap(&php,89);
printf("%d\n",PopHeap(&php));
printf("%d\n", PopHeap(&php));
printf("%d\n", PopHeap(&php));
printf("%d\n", PopHeap(&php));
printf("%d\n", PopHeap(&php));
printf("%d\n", PopHeap(&php));
printf("%d\n", PopHeap(&php));
//printf("%d\n", PopHeap(&php));
for (i = 0; i < hp.size; i++)
{
printf("%d ", hp.arr[i]);
}
return 0;
}