一、什么是堆
1.堆是一种特殊的完全二叉树,就像下边这棵树一样: 2.发现: 我们发现这棵树的所有父节点都比子节点要小,符合这样的完全二叉树我们称为最小堆。 最大堆:如果二叉树的所有父节点都比子节点要大,就称为最大堆。
二、堆可以用来干什么
1.问题描述 加入有14个数,分别是99,5,36,7,22,17,46,12,2,19,25,28,1,92. 请找出这14个数中最小的数,请问应该怎么办呢? 最简单的方法就是将14个数从小扫描到尾,用一个循环就可以解决,但是这种方法的时间复杂度是O(14),也就是O(N)。 如果我们先删除最小的数,再需要增加一个新数23,并且再次求这14个数的最小数,那么这个时候时间复杂度就是O(N的平方)。
2.思路解析 上边的问题可以用堆很简单的解决。 首先我们将14个数按照最小堆的要求(就是所有的父节点都要比子节点小)放入一棵完全二叉树,就像下边的这棵树一样: 很显然最小的数就在堆顶,假设存储这个堆的数组叫做h的话,最小数就是h[1]. 接下来我们将堆顶部的数删除,将新增加的23放在对顶,再次调节为最小堆。 如何调整为最小堆呢,向下调整,将23与两个儿子做对比,选择较小的一个与它交换,交换后如下: 我们发现此时还不符合最小堆的特性,继续讲下调整。 于是继续将23与它的两个儿子交换,结果如下: 这样我们就实现了最小堆,知道了最小数。
3.代码复现 向下调整的代码如下:
void siftdown(int i)
{
int t,flag=0;
while( i*2<=n && flag==0)
{
if( h[i]>h[i*2])
t=i*2;
else
t=i;
if( i*2+1<=n)
{
if( h[t]>h[i*2+1])
t=i*2+1;
}
if(t!=i)
{
swap(t,i);
i=t;
}
else
flag=1;
}
}
三、堆排序
与快速排序一样,堆排序的时间复杂度也是O(NlogN) . 如果我们现在要进行从小到大的排序,首先建立最小堆,然后每次删除顶部元素并将顶部元素输出或者放在一个新的数组中,直到堆空为止。最终输出的就是一个排序的序列。
1.建立最小堆,从小到大排序。
代码实现
#include<stdio.h>
int h[101];
int n;
void swap(int x,int y)
{
int t;
t=h[x];
h[x]=h[y];
h[y]=t;
}
void siftdown(int i)
{
int t,flag=0;
while( i*2<=n && flag==0)
{
if( h[i]>h[i*2])
t=i*2;
else
t=i;
if( i*2+1<=n)
{
if( h[t]>h[i*2+1])
t=i*2+1;
}
if(t!=i)
{
swap(t,i);
i=t;
}
else
flag=1;
}
}
void creat()
{
int i;
for(i=n/2;i>=1;i--)
{
siftdown(i);
}
}
int deletemax()
{
int t;
t=h[1];
h[1]=h[n];
n--;
siftdown(1);
return t;
}
int main()
{
int i,num;
scanf("%d",&num);
for(i=1;i<=num;i++)
{
scanf("%d",&h[i]);
}
n=num;
creat();
for(i=1;i<=num;i++)
printf("%d ",deletemax());
getchar();
getchar();
return 0;
}
2.建立最大堆,从小到大排序。
代码实现
#include<stdio.h>
int h[101];
int n;
void swap(int x,int y)
{
int t;
t=h[x];
h[x]=h[y];
h[y]=t;
}
void siftdown(int i)
{
int t,flag=0;
while( i*2<=n && flag==0)
{
if( h[i]<h[i*2])
t=i*2;
else
t=i;
if( i*2+1<=n)
{
if( h[t]<h[i*2+1])
t=i*2+1;
}
if(t!=i)
{
swap(t,i);
i=t;
}
else
flag=1;
}
}
void creat()
{
int i;
for(i=n/2;i>=1;i--)
{
siftdown(i);
}
}
void heapsort()
{
while(n>1)
{
swap(1,n);
n--;
siftdown(1);
}
}
int main()
{
int i,num;
scanf("%d",&num);
for(i=1;i<=num;i++)
{
scanf("%d",&h[i]);
}
n=num;
creat();
heapsort();
for(i=1;i<=num;i++)
printf("%d ",h[i]);
getchar();
getchar();
return 0;
}
|