首先要和大家说一说堆得基本概念,也就是堆是什么:如果有一个关键码的集合,把他的所有元素按完全二叉树的顺序存储方式存储在一个一维数组
,并满足;
Ki <= K2*i+1 且 Ki<= K2*i+2
(Ki >= K2*i+1 且 Ki >= K2*i+2) i =0,1,2...,则
称为小堆
(或大堆)。
小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左右孩子的关键码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数组元素组成的序列都是递增(递减)的
堆存储在下标为0开始的数组中,因此在堆中给定下标为i的结点时:
如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为结点(i-1)/2
如果2 * i + 1 <= n - 1,则结点i的左孩子为结点2 * i + 1,否则结点i无左孩子
如果2 * i + 2 <= n - 1,则结点i的右孩子为结点2 * i + 2,否则结点i无右孩子
如图
将二叉树调整为最小堆的原理:
从最后一个非叶子结点开始调整,一直到根节点为止,将每个结点及其子
树调整到满足小堆的性质即可
具体方法如下
1假设该节点的下标为parent
2找到该节点的左孩子 right=parent*2+1;
3如果右孩子也在,比较找出左右孩子中最小的孩子
4比较parent与最小的孩子,如果比最小的孩子小,那么调整结束
否则将最小孩子与parent交换此时有可能导致其子树不满足堆的性质,继续其子树直到满足堆的性质
堆的插入和删除
插入;
堆的插入;在建成最小堆的后面插入新元素,插入之后,当树中结点不满足堆的性质时,就需要对堆进行重新调整
删除;
堆的删除时,每次删除堆顶元素
删除方法
1用堆中最后一个元素,代替堆顶元素
2将堆的元素个数减少一个,相当于删除了最后一个元素。
3此时堆结构可能被破坏,应堆顶向下调整使再次满足堆的性质。
以上是我对堆的一点理解,下面是我实现的代码
#include <malloc.h>
#include<assert.h>
typedef int DataType;
typedef struct Heap
{
DataType* _array;//存放堆的数组
int _capacity;//数组的容量
int _size;//已存数组的大小
}Heap;
void Swap(DataType *pLeft,DataType*pRight)//交换数值
{
DataType temp;
assert(pLeft);
assert(pRight);
temp=*pLeft;
*pLeft=*pRight;
*pRight=*pLeft;
}
void _AdjustDown(Heap*hp,int parent)//向下调整
{
//标记左右孩子中最小孩子
int child=parent<<1+1;
int size=hp->_size;
while(child<size)
{
if (child+1<size&&hp->_array[child]>hp->_array[child+1])//有右子树时 ,找左右孩子中最小的孩子
child=child+1;
if(hp->_array[child]<hp->_array[parent])//最小孩子小于双亲时 ,孩子与双亲数值交换,否则说明已经调好,不用继续
{
Swap(&hp->_array[child],&hp->_array[parent]);
parent=child;
child =parent<<1;
}
else
return ;
}
}
void CreateHeap(Heap*hp,DataType*array,int size)//创建
{
int i=0;
int root=(size-2)>>1;
if (hp==NULL)
return;
//给堆申请空间
hp->_array=(DataType*)malloc(sizeof (DataType)*size);
if (hp->_array==NULL)
{
assert(0);
return ;
}
//数组中元素放到堆中
for (;i<size;++i)
hp->_array[i]=array[i];
hp->_capacity=size;
hp->_size=size;
//堆调整
for (;root>=0;root--)
{
_AdjustDown(hp,root);
}
}
void _AdjustUp(Heap*hp,int child)//向上调整
{
int parent=(child-1)>>1;
while (child)
{
if(hp->_array[child]<hp->_array[parent])
{ Swap(&hp->_array[child],&hp->_array[parent]);
child=parent;
parent =(child-1)>>1;
}
else
return;
}
}
int EmptyHeap(Heap*hp)//判空
{
assert(hp);
return 0==hp->_size;
}
void _CheckCapacity(Heap*hp)//扩容
{
int i=0;
int newcapacity=0;
DataType* temp=NULL;
assert (hp);
if (hp->_size==hp->_capacity)
{
newcapacity=hp->_capacity*2;
DataType* temp=(DataType*)malloc(sizeof(DataType)*newcapacity);
if (NULL==temp)
{
assert (temp);
return;
}
for (i=0;i<hp->_size;i++)//老数组元素插入新数组
{
temp[i]=hp->_array[i];
}
free(hp->_array);
hp->_array=temp;
hp->_capacity=newcapacity;
}
}
void InsertHeap(Heap*hp,DataType data)
{
int child=0;
int parent=0;
assert(hp);
_CheckCapacity(hp);
hp->_array[hp->_size++]=data;//插入到最后一个元素的下一个位置
//调整刚插入元素,
_AdjustUp(hp,hp->_size-1);
}
void DeleteHeap(Heap*hp)//删除堆顶
{
if (EmptyHeap(hp))
return ;
hp->_array[0]=hp->_array[hp->_size-1];//用最后一个元素覆盖堆顶,相当于删除堆顶
hp->_size—;//删除最后一个元素
_AdjustDown(hp,0);//对第一个元素进行调整
}
void TestHeap()
{
int arr[]={53,17,78,9,45,65,87,23,31};
Heap hp;
CreateHeap(&hp,arr,sizeof(arr)/sizeof(arr[0]));
InsertHeap(&hp,5);
DeleteHeap(&hp);
}
int SizeHeap(Heap*hp)
{
assert (hp);
return hp->_size;
}
int main ()
{
TestHeap();
168,1-8 98%