堆的概念
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: Ki <= K2*i+1 且 Ki<= K2*i+2 (Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称为小堆(或大堆)。
小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左右孩子的关键 码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数 组元素组成的序列都是递增(递减)的
堆存储在下标为0开始的数组中,因此在堆中给定下标为i的结点时:
- 如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为 结点(i-1)/2
- 如果2 * i + 1 <= n - 1,则结点i的左孩子为结点2 * i + 1,否则结 点i无左孩子
- 如果2 * i + 2 <= n - 1,则结点i的右孩子为结点2 * i + 2,否则结 点i无右孩子
堆的创建,插入,删除,堆排序
代码实现
Heap.h
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
typedef int HPDataType;
typedef struct Heap
{
HPDataType* _a;
int _size;
int _capacity;
}Heap;
void HeapInit(Heap* hp, HPDataType* a, int n);
void HeapDestory(Heap* hp);
void HeapPush(Heap* hp, HPDataType x);
void HeapPop(Heap* hp);
HPDataType HeapTop(Heap* hp);
int HeapSize(Heap* hp);
int HeapEmpty(Heap* hp);
// 不要直接调Heap
void HeapSort(HPDataType* a, int n);
void HeapPrint(Heap* hp);
void TestHeap();
Heap.c
#include"Heap.h"
void Swap(HPDataType* x1, HPDataType*x2)
{
HPDataType x = *x1;
*x1 = *x2;
*x2 = x;
}
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]<a[child+1])
{
child++;
}
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void AdJustUp(HPDataType*a, int child)
{
assert(a);
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[parent] < a[child])
{
Swap(&a[parent], &a[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void HeapInit(Heap* hp, HPDataType* a, int n)
{
assert(hp&&a);
hp->_a = (HPDataType*)malloc(sizeof(HPDataType)*n);
hp->_size = n;
hp->_capacity = n;
for (int i = 0; i < n; ++i)
{
hp->_a[i] = a[i];
}
//调堆
for (int i = (n - 2) / 2; i >= 0; --i)
{
AdJustDown(hp->_a, hp->_size, i);
}
}
void HeapDestory(Heap* hp)
{
assert(hp);
free(hp->_a);
hp->_a = NULL;
hp->_size = hp->_capacity = 0;
}
void HeapPush(Heap* hp, HPDataType x)
{
assert(hp);
if (hp->_capacity == hp->_size)
{
hp->_capacity *= 2;
hp->_a = (HPDataType*)realloc(hp->_a,sizeof(HPDataType)*hp->_capacity);
}
hp->_a[hp->_size++] = x;
AdJustUp(hp->_a, hp->_size - 1);
}
void HeapPop(Heap* hp)
{
assert(hp);
Swap(&hp->_a[0], &hp->_a[hp->_size - 1]);
hp->_size--;
AdJustDown(hp->_a, hp->_size, 0);
}
HPDataType HeapTop(Heap* hp)
{
assert(hp);
return hp->_a[0];
}
int HeapSize(Heap* hp)
{
assert(hp);
return hp->_size;
}
int HeapEmpty(Heap* hp)
{
assert(hp);
return hp->_size > 0 ? 1 : 1;
}
//升序
void HeapSort(HPDataType* a, int n)
{
//建大堆
int i = 0;
for (i = (n - 2) / 2; i >= 0; --i)
{
AdJustDown(a, n, i);
}
int end = n - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
//调堆 选次大的数
AdJustDown(a, end, 0);
--end;
}
return 0;
}
void HeapPrint(Heap* hp)
{
for (int i = 0; i < hp->_size; ++i)
{
printf("%d ", hp->_a[i]);
}
printf("\n");
}
void TestHeap()
{
Heap hp;
HPDataType a[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
HeapInit(&hp, a, sizeof(a) / sizeof(a[0]));
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ", a[i]);
}
printf("\n");
HeapPush(&hp, 100);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
printf("%d \n", HeapSize(&hp));
printf("%d \n", HeapTop(&hp));
}
int main()
{
int a[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
TestHeap();
return 0;
}