什么是堆
堆是一个数据结构的统称,堆通常是一个可以被看做一棵树的数组对象。满足下列性质
- 堆中某个节点的值总是不大于或不小于其父节点的值
- 堆总是一棵完全二叉树
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
大堆: 任意一个结点的值关键码(值)均大于等于它的左右孩子的关键码(值),位于对顶结点的关键码最大,从根节点到每个结点的路径上数组元素组成的序列都是递减的。
小堆: 任意一个结点的值关键码(值)均小于等于它的左右孩子的关键码(值),位于对顶结点的关键码最最小,从根节点到每个结点的路径上数组元素组成的序列都是递增的。
堆的基本操作
堆的创建
- 先申请一块空间,然后对其赋值形成二叉树,在对二叉树进行调整形成小堆
void CreateHeap(Heap * hp, int * array, int size,Compare com)
{
int i = 0;
int Root = 0;
assert(hp);
hp->_array = (DataType *)malloc(sizeof(DataType)*size);
if(NULL == hp->_array)
{
printf("内存申请失败!!!\n");
assert(0);
}
hp->_size = 0;
hp->_capacity = size;
hp->com = com;
//赋值
for(i=0; i< size; ++i)
{
hp->_array[i] = array[i];
hp->_size += 1;
}
//找出最后一个非叶子结点
Root = (size-1) >> 1;
for(; Root >= 0; --Root)
AdjustDown(hp,Root);
}
向下调整(形成小堆)
- 找到最后一个非叶子结点
- 以非叶子结点进行判断是否是小堆
- 如果不是进行调整
- 调整完后,可能该结点的孩子结点的值被改变,所以需要继续调整以孩子结点为根节点的二叉树,直到无元素可调或者超出元素的范围
- 继续调整其他非叶子结点,知道把第一个非叶子结点调整完后,就形成了小堆
void AdjustDown(Heap * hp,int parent)
{
int child = (parent << 1) + 1;
assert(hp);
while(child < hp->_size)
{
//找到孩子中较小的一个
if(child+1 < hp->_size && hp->com(hp->_array[child+1],hp->_array[child]))
{
child += 1;
}
//括号里面是一个函数指针,根据传来的参数确定需要大堆还是小堆
//如果双亲大于孩子,则交换
if(hp->com(hp->_array[child],hp->_array[parent]))
{
swap(&hp->_array[parent],&hp->_array[child]);
parent = child;
child = (parent+1) << 1;
}
else
{
break;
}
}
}
插入元素
- 检测容量,如果空间已满,警醒扩容
- 将元素插到堆的最后面
- 进行向上调整
void InsertHeap(Heap* hp, DataType data)
{
assert(hp);
CheckCatacity(hp);
hp->_array[hp->_size] = data;
hp->_size += 1;
if(hp->_size>1)
//向上调整
AdjustUp(hp,hp->_size-1);
}
向上调整
- 使用传来的结点序号为孩子结点,进行与父节点进行比较,小于父节点交换,大于则调整完毕
void AdjustUp(Heap* hp,int child)
{
int parent = (child-1) >> 1;
while(child)
{
if(hp->com(hp->_array[child],hp->_array[parent]))
{
swap(&hp->_array[parent],&hp->_array[child]);
child = parent;
parent = (child-1) >> 1;
}
else
break;
}
}
删除对顶元素
- 将堆顶元素与最后一个元素进行交换
- 有效个数减1
- 调整二叉树数为需要的堆
void DeleteHeap(Heap* hp)
{
assert(hp);
swap(&hp->_array[0],&hp->_array[hp->_size-1]);
hp->_size -= 1;
AdjustDown(hp,0);
}
void printHeap(Heap hp)
{
int i = 0;
for(i=0; i<hp._size; ++i)
{
printf("%d ",hp._array[i]);
}
printf("\n");
}