二叉堆
*在信息学奥赛中常会遇到给你一个数列,让你求最大值或最小值的问题,这个问题很简单,但是一旦遇到频繁查找那就很复杂了,这里就要涉及到一个新的数据结构,二叉堆.
一、堆的定义
堆的定义:n个元素的序列K={a1,a2,a3,…an},当且仅当满足如下条件时,称之为堆。Ki<=K2i且Ki<=K2i+1或者Ki>=K2i且Ki>=K2i+1,(i=1,2,… 可以看出,若将此序列看成完全二叉树.则堆的定义表明,完全二叉树中每个非结点的关键字均小于等于 (或大于等于)其左右子结点.这样根就成了最小或最大值.堆也因此称为小根堆或大根堆.由此可见,从堆中获取最小 (大)值是很方便的.堆的子树也满足堆得性质.
二、堆的存储方式
[存储方式]最小堆的元素保存在a[1…n]内
– 根在a[1]
– K的左儿子是2k, K的右儿子是2k+1,
– K的父亲是[k/2]
三、堆的基本操作
1.删除最小值
• 三步法
①直接删除根
②用最后一个元素代替根上元素
③向下调整
void heapdown()//向下堆化
{
int t,i,j;
i=1;
while(i*2<=a[0])//a[0]表示堆的大小
{
if(i*2==a[0]||a[i*2]<a[i*2]+1)
j=i*2;
else
j=i*2+1;
if(a[i]>a[j])
{
swap(a[i],a[j]);
i=j;
}
else
break;
}
return;
}
int deleteMin()//删除堆顶元素
{
int r=a[1];
a[1]=a[a[0]--];
heapdown(1);
return r;
}
2.插入元素和向上调整
• 插入元素是先添加到末尾, 再向上调整
• 向上调整:比较当前结点p和父亲, 如果父亲比p小,停止; 否则交换父亲和p, 继续调整
void heapup()//向上堆化
{
int i,t;
i=a[0];
while(i>1&&a[i]<a[i/2])
{
swap(a[i],a[i/2]);
i=i/2;
}
return