一、简单了解堆
如果有一个关键码的集合k = {k0,k1,k2,...,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:ki <= k21+1 且 ki <= k2i+2(ki >= k2i+1 且 ki >= k2i+2) i = 0,1,2...,则称为小堆(或大堆)。将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。
堆的性质:
·堆中某个节点的值总是不大于或不小于其父节点的值;
·堆总是一棵完全二叉树。
二、堆的实现
具体实现:
1.堆的向下调整:将堆变成小堆或大堆(前提:调整的树左右子树必须是一个堆,才能调整)
2.对的创建:从倒数第一个非叶子节点的子树开始调整,一直调整到节点的树,就可以调整成堆。
3.堆的插入:先插入一个值到数组的尾上,再进行向上调整的算法,直到满足堆。
4.堆的删除:删除堆是删除堆顶的数据,将堆顶的数据和最后一个数据一换,然后删除数组最后一数据,再进行向下调整算法。
5.堆排序:结合了建堆和向下调整,先建堆然后将堆顶元素和数组最后一个元素交换,再将堆顶元素进行向下调整,直到排好序。
三、代码实现
#pragma once
#include <stdlib.h>
#include <assert.h>
//向下调整
//array[size]表示数组及大小
//root表示要调整的结点的下标
//前提是[root]所在结点左右子树已经满足堆的性质
void AdjustDown(int array[], int size, int root)
{
//int left = 2 * root + 1;
//int right = 2 * root + 2;
int min = 2 * root + 1;
if (min >= size)
{
//越界
return;
}
//确定那个是最小的孩子
if (min+1 < size && array[min+1] < array[min])
{
min = min+1;
}
if (array[root] <= array[min])
{
return;
}
//交换值
int tmp = array[root];
array[root] = array[min];
array[min] = tmp;
AdjustDown(array, size, min);
}
//建堆
void CreateHeap(int array[], int size)
{
//从最后一个非叶子结点开始,调整到0结束
//最后一个非叶子结点就是最后一个结点的双亲结点
for (int i = (size - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(array, size, i);
}
}
typedef int HPDataType;
typedef struct Heap
{
HPDataType* array;
int size;
int capacity;
} Heap;
//初始化
void HeapCreateHeap(Heap* heap, int array[], int size)
{
heap->capacity = size * 2;
heap->size = size;
heap->array = (HPDataType*)malloc(sizeof(HPDataType) * size);
for (int i = 0; i < size; ++i)
{
heap->array[i] = array[i];
}
//建堆
CreateHeap(heap->array, heap->size);
}
//小堆
void AdjustUp(int array[], int size, int child)
{
while (child != 0)
{
int parent = (child - 1) / 2;
if (array[child] >= array[parent])
{
return;
}
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
child = parent;
}
}
//增加
void HeapInsert(Heap* heap, int val)
{
heap->array[heap->size] = val;
++heap->size;
AdjustUp(heap->array, heap->size, heap->size - 1);
}
//删除(只能删除堆顶元素)
void HeapPop(Heap* heap)
{
assert(heap->size > 0);
heap->array[0] = heap->array[heap->size - 1];
--heap->size;
AdjustDown(heap->array, heap->size, 0);
}
//堆排序
void HeapSort(int *array, int size)
{
CreateHeap(array, size);
while (size--){
int tmp = array[0];
array[0] = array[size];
array[size] = tmp;
AdjustDown(array, size, 0);
}
}
//返回堆顶元素,返回最值
HPDataType HeapTop(Heap* heap)
{
assert(heap->size > 0);
return heap->array[0];
}