堆
1. 定义: 堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。
堆总是满足下列性质:
①堆中某个节点的值总是不大于或不小于其父节点的值;
②堆总是一棵完全二叉树。
2. 应用: 我们用堆排可以实现时间复杂度为
n
∗
l
o
g
n
n * logn
n∗logn 排序。
3. 类型: 大顶堆(堆顶是堆里最大的元素),小顶堆(堆顶是堆里最小的元素)。
下面我们以小顶堆来看几种操作(a为数组,size为数组长度)
引用学长的blog来说一下堆排思路:再话堆排序
我们既然已经学会了堆的调整,那么我们想,如果现在有一个大顶堆的存在,我们把他的堆顶(最大的那个元素)与最后一个元素进行交换的话,然后把堆的规模缩小1(也就是最后一个元素不在堆里面了)然后重新调整新的堆,在进行刚才的交换操作,直到最后是不是就是一个从小到大的有序数组呢。然后我们考虑每次调整的复杂度是多少,每次最坏的调整复杂度就是从根一直到最下面的叶子节点,也就是树的高度,复杂度为树的高度(logn),然后需要调整n次也就是整体复杂度为n∗log(n) n*log(n)n∗log(n)
建堆
void Insert(int x)
{
int t,i;
a[++size]=x;
for(i=size; i!=0; i/=2)
{
if(a[i]<a[i/2]) //建立大顶堆这里要改成>,同时还要注意
{ //一个问题,当i=1时,这里会变成
t=a[i]; //a[1]>a[0],但是我们的a[0]初始值是
a[i]=a[i/2];//0的,所以会出现有值被交换到a[0]上,
a[i/2]=t; //因此我们需要在此之前对a[0]进行初始化
}
else
break;
}
}
堆的删除
void Delete() //我们以删除堆顶元素为例
{
int t,p,i;
a[1]=a[size--];
for(i=1; i*2<=size; i = p)
{
if(i*2+1<=size&&a[i*2]>a[i*2+1])
p= i*2+1;
else
p= i*2;
if(a[p]<a[i])
{
t=a[i];
a[i]=a[p];
a[p] =t;
}
else
break;
}
}
堆的调整
void Adjust(int *a,int n)
{
int i,p,t;
for(i=1; i*2<=n; i = p)
{
if(i*2+1<=n&&a[i*2]>a[i*2+1])
p= i*2+1;
else
p= i*2;
if(a[p]<a[i])
{
t=a[i];
a[i]=a[p];
a[p] =t;
}
else
break;
}
}
堆排
void HeapSort(int *a, int n)
{
int i,t;
for(i = n; i >= 1; i--)
{
swap(a[1], a[i]);
Adjust(a,i-1);
}
}