一、堆的概念及结构
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树。
- 堆顶元素一定是最大的或最小的
二、堆的实现
1、堆向下调整算法
现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。
int a[] = {27,15,19,18,28,34,65,49,25,37};
//思路
//1、找parent较小的孩子
int child=parent*2+1;//parent的左孩子
while(child<size){
//保证右孩子存在:child+1<size
if(child+1<size&&array[child+1]<array[child])
child+=1;
//检测parent是否满足堆得性质
if(array[child]<array[parent])
Swap(&array[parent],&array[child]);
//双亲比孩子大,交换完成后,较大的双亲往下移动,可能会导致字数不满足堆的性质
parent=child;
child=parent*2+1;
else
return;
}
2、堆的创建
下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。
int a[] = {1,5,3,8,7,6};
3、堆的插入
先插入一个80到数组的尾上,再进行向上调整算法,直到满足堆。
4、 堆的删除
删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
5 、堆排序
三、堆得代码实现
typedef int HDataType;
int Less(HDataType left, HDataType right);
int Greater(HDataType left, HDataType right);
//函数指针变量:可以指向任何有两个HDataType参数以及一个int类型返回值得所有函数
//cmp势函数指针变量,Cmp可以指向Less,也可以指向Greater
//Cmp的类型:int(*)(HDataType,HDataType)
static int (*Cmp)(HDataType left, HDataType right);
typedef int(*CMP)(HDataType, HDataType);
typedef struct Heap
{
HDataType* array;
int capacity;
int size;
CMP Cmp;//函数指针变量
}Heap;
int Less(HDataType left, HDataType righ