1.堆
堆(Heap)是一种特殊的完全二叉树数据结构,具有以下两个主要特性:
- 结构特性:
- 堆是一棵完全二叉树,即除了最后一层的叶子节点外,每一层都是满的,最后一层的叶子节点从左向右依次排列。
- 堆序性:
- 大堆(Max-Heap):对于每个节点,父节点的值大于或等于其子节点的值。大堆中,根节点的值是所有节点中最大的。
- 小堆(Min-Heap):对于每个节点,父节点的值小于或等于其子节点的值。小堆中,根节点的值是所有节点中最小的。
2.堆的实现
2.1堆的定义
typedef int HPDataType;
typedef struct Heap
{
HPDataType* a;
size_t size;
size_t capacity;
}HP;
2.2堆初始化
void HeapInit(HP* php)
{
assert(php);
php->a = NULL;
php->size = php->capacity = 0;
}
2.3堆的销毁
void HeapDestroy(HP* php)
{
assert(php);
free(php->a);
php->a = NULL;
php->size = php->capacity = 0;
}
2.3打印
void HeapPrint(HP* php)
{
assert(php);
for (size_t i = 0; i < php->size; ++i)
{
printf("%d ", php->a[i]);
}
printf("\n");
}
2.4向上调整堆的顺序(小堆)
向上调整,只是传入子节点下标,类似与向下调整算法。
void Swap(HPDataType* pa, HPDataType* pb)
{
HPDataType tmp = *pa;
*pa = *pb;
*pb = tmp;
}
void AdjustUp(HPDataType* a, size_t child)
{
size_t parent = (child - 1) / 2;
while (child > 0)
{
if (a[child] < a[parent]) //小堆
//if (a[child] > a[parent]) //大堆
{
Swap(&a[child], &a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
2.5向堆中插入数据
将数据插入到最后一个,然后利用向上调整算法
void HeapPush(HP* php, HPDataType x)
{
assert(php);
if (php->size == php->capacity)
{
size_t newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
HPDataType* tmp = realloc(php->a, sizeof(HPDataType)* newCapacity);
if (tmp == NULL)
{
printf("realloc failed\n");
exit(-1);
}
php->a = tmp;
php->capacity = newCapacity;
}
php->a[php->size] = x;
++php->size;
// 向上调整,控制保持是一个小堆
AdjustUp(php->a, php->size - 1);
}
2.6向下调整堆的顺序(小堆)
void AdjustDown(HPDataType* a, size_t size, size_t root)
{
size_t parent = root;
size_t child = parent * 2 + 1;
while (child < size)
{
// 1、选出左右孩子中小的那个
if (child + 1 < size && a[child+1] < a[child])
{
++child;
}
// 2、如果孩子小于父亲,则交换,并继续往下调整
if (a[child] < a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
2.7删除堆顶的数据。
// 删除堆顶的数据。
void HeapPop(HP* php)
{
assert(php);
assert(php->size > 0);
Swap(&php->a[0], &php->a[php->size - 1]);
--php->size;
AdjustDown(php->a, php->size, 0);
}
2.8判断堆是否为空
bool HeapEmpty(HP* php)
{
assert(php);
return php->size == 0;
}
2.9查看堆的大小
size_t HeapSize(HP* php)
{
assert(php);
return php->size;
}
2.10返回堆顶数据
HPDataType HeapTop(HP* php)
{
assert(php);
assert(php->size > 0);
return php->a[0];
}