概念
堆是什么?
堆是一种特殊的完全二叉树,所以堆的底层通过数组实现
小堆:所有父节点的值小于其子节点的值。
大堆:所有父节点的值大于其子节点的值。![在这里插入图片描述](https://img-
**
堆的基本操作解析
**
建堆
1.先申请一块空间,然后对其赋值,逻辑上看为完全二叉树,然后对二叉树结构进行调整。(从对的倒数第一个非叶子节点向下调整,一直调整到堆的根节点,就可以调整成堆了)
向下调整算法(小堆)
1.设该节点下标为parent,
2.找到左孩子child = parent*2+1,如果右孩子存在比较左右孩子找出最小的孩子(大堆反之)
3.比较parent与最小孩子child的大小,如果parent<child,swap(parent,child)直到调整结束。
堆的插入
1.先检查是否需要扩容,
2.将数据插入到数组的结尾,
3.向上调整堆(通过child计算他的parent ,再比较child与parent,与向下调整类似)
堆的删除
删除堆是删除堆顶的数据,将堆顶的数据跟最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
**
代码实现:
typedef int HPDataType;
typedef struct Heap
{
HPDataType * array;
int capacity;
int size;
}Heap;
void Swap(HPDataType* left, HPDataType * right)
{
int temp = *left;
*left = *right;
*right = temp;
}
void Checkcapacity(Heap *hp)
{
assert(hp);
if (hp->size >= hp->capacity)
{
int newcapacity = 2 * hp->capacity;
HPDataType* temp = (HPDataType *)malloc(sizeof(HPDataType)*newcapacity);
if (temp == NULL)
{
assert(0);
return;
}
memcpy(temp, hp->array, hp->size*sizeof(HPDataType));
free(hp->array);
hp->array = temp;
hp->capacity = newcapacity;
}
}
void AdjistDown(Heap *hp,int parent)
{
int child = parent * 2 + 1;
while (child<hp->size)
{
if (child +1 <hp->size && hp->array[child] > hp->array[child + 1])
{
child++;
}
if (hp->array[child] < hp->array[parent])
{
Swap(&hp->array[child], &hp->array[parent]);
parent = child;
child = parent * 2+1;
}
else
{
return;
}
}
}
void CreatHeap(Heap* hp, HPDataType arr[], int size)
{
assert(hp);
hp->array = (HPDataType *)malloc(sizeof(HPDataType)*size);
if (hp->array == NULL)
{
assert(0);
return;
}
hp->capacity = size;
memcpy(hp->array, arr, sizeof(HPDataType)*size);
hp->size = size;
for (int root = (size - 2) / 2; root >= 0; root--)
{
AdjistDown(hp, root);
}
}
void Heappush(Heap* hp, HPDataType data)
{
assert(hp);
Checkcapacity(hp);
hp->array[hp->size++] = data;
Adjistup(hp, hp->size - 1);
}
void Heappop(Heap* hp)
{
assert(hp);
if (Heapempty(hp))
{
return;
}
Swap(&hp->array[0], &hp->array[hp->size-1]);
hp->size--;
AdjistDown(hp, 0);
}
void Heapdestroy(Heap * hp)
{
assert(hp);
if (hp->array)
{
free(hp->array);
hp->array = NULL;
hp->size = 0;
hp->capacity = 0;
}
}
堆排序
升序建大堆,降序建小堆
堆排序就是利用堆删除元素的特性进行排序
先建堆 在循环进行heappop();
时间复杂度为O(nlogn);
空间复杂度O(1);
但是堆排序不稳定
代码实现:
void Adjistdown(int array[],int size,int parent)
{
int child = parent * 2 + 1;
while (child < size)
{
if (child + 1 < size&&array[child] > array[child + 1])
{
child += 1;
}
if (array[child] < array[parent])
{
int temp = array[parent];
array[parent] = array[child];
array[child] = temp;
parent = child;
;
child = parent * 2 + 1;
}
else
{
return;
}
}
}
void heapsort(int array[],int size)
{
for (int root = (size - 2) >> 1; root >= 0; root--)
{
Adjistdown(array, size, root);
}
int end = size - 1;
while (end)
{
int temp = array[end];
array[end] = array[0];
array[0] = temp;
Adjistdown(array, end, 0);
end--;
}
}