1.堆的概念与结构
(1)堆是一棵完全二叉树
(2)堆的物理结构为顺序结构存储,即使用数组来存储
(3)堆的逻辑结构,如图所示
parent=(leftchild-1)/2;
parent=(rightchild-1)/2;
leftchild=parent*2+1;
rightchild=parent*2+2;
有大堆与小堆的分别
大堆:所有的父节点大于或等于所有的子节点
小堆:所有的父节点小于或等于所有的子节点
2.堆的实现
//堆的创建
typedef int HeapDateType;
typedef struct Heap
{
HeapDateType* a;
int sz;
int capicity;
}HP;
//初始化堆
void HeapInit(HP* php)
{
assert(php);
php->a = NULL;
php->capicity = php->sz = 0;
}
重点一:向堆中插入数据
将parent与child所指向的对象进行比较,若parent所指向的对象小于child所指向的对象,则进行交换,如此往复
//向堆中插入数据
void HeapPush(HP* php, HeapDateType x);
//向上调整
void Adjustup(HeapDateType* a, int child);
void Swap(HeapDateType* pa, HeapDateType* pb);
void HeapPush(HP* php, HeapDateType x)
{
assert(php);
if (php->capicity == php->sz)
{
php->capicity = php->capicity * 2 + 1;
HeapDateType* tmp =
(HeapDateType*)realloc(php->a, sizeof(HeapDateType) * php->capicity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
php->a = tmp;
}
}
php->a[php->sz] = x;
Adjustup(php->a,php->sz);
php->sz++;
}
void Adjustup(HeapDateType* a,int child)
{
int parent = (child - 1) / 2;
//大堆
while (child>0)
{
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
重点二:删除堆顶的数据
(1)将最后一个元素覆盖到堆顶
(2)将leftchild和rightchild指向的元素进行比较,去取其大big与parent指向的元素进行比较,若big指向的元素大于parent所指向的元素则进行交换,如此往复
ps(当rightchild超出堆的范围时,要进行特殊处理)
//删除堆顶的数据
void HeapPop(HP* php);
//向下调整
void Adjustdown(HeapDateType* a, int sz, int root);
void Adjustdown(HeapDateType* a, int sz, int root)
{
int parent = root;
int child;
//大堆
while (parent<=(sz-2)/2)
{
child = parent * 2 + 1;
//选出左右孩子小的那个
if (child + 1 < sz && a[child + 1] > a[child])
{
child++;
}
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
}
else
break;
}
}
void HeapPop(HP* php)
{
assert(php);
php->a[0] = php->a[php->sz - 1];
php->sz--;
Adjustdown(php->a, php->sz - 1, 0);
}