几个基础概念:
优先队列:支持插入元素和寻找最大(小)值元素的数据结构。
根结点为第一层
满二叉树:树高为h且
结点总数
完全二叉树:树高为h且
结点总数
完全二叉树:最后一个非叶结点是第n/2个结点
下面的程序是建堆(最小堆、最大堆),利用堆来设计优先队列,而后设计堆进行排序。
可以看到,建堆时间复杂度为,利用堆设计的优先队列时间复杂度为
,堆排序的时间复杂度为
。
测试程序:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int a[100];
int sum=0;
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
int t;
scanf("%d",&t);
sum++;
a[sum]=t;
int k=sum;
while(k>1)
{
if(k/2>=1&&a[k/2]>=a[k])
{
swap(a[k/2],a[k]);
k=k/2;
}
else
break;
}
}
int m;
scanf("%d",&m);
while(m--)
{
int x;
scanf("%d",&x);
cout<<a[1]<<endl;
a[1]=x;
int t=1;
int flag=t;
while(2*flag<=n)
{
t=flag;
if(a[t]>=a[2*t])
{
flag=2*t;
}
if(2*t+1<=n)
{
if(a[flag]>=a[2*t+1])
{
flag=2*t+1;
}
}
if(flag==t)
break;
else
{
swap(a[t],a[flag]);
}
}
}
for(int i=1; i<=n; i++)
{
printf("%d ",a[i]);
}
cout<<endl;
while(1)
{
cout<<a[1]<<" ";
a[1]=a[n];
n--;
if(n==0)
break;
int t=1;
int flag=t;
while(2*flag<=n)
{
t=flag;
if(a[t]>=a[2*t])
{
flag=2*t;
}
if(2*t+1<=n)
{
if(a[flag]>=a[2*t+1])
{
flag=2*t+1;
}
}
if(flag==t)
break;
else
{
swap(a[t],a[flag]);
}
}
}
}
测试结果:
如果有一个大小为n的数列,从中选择第k大的数据,使用堆将会大大提升缀合速度,时间可以优化到
如果使用快排处理,需要
如果使用冒泡,需要
测试程序:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int a[100];
int sum=0;
int main()
{
int n,k;
scanf("%d %d",&n,&k);
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&x);
sum++;
if(sum<=k)
{
a[sum]=x;
int flag=sum;
while(flag>1)
{
if(flag/2>=1&&a[flag]<a[flag/2])
{
swap(a[flag],a[flag/2]);
flag=flag/2;
}
else
break;
}
}
else
{
if(x>a[1])
{
a[1]=x;
int flag=1;
int t;
t=flag;
while(flag*2<=k)
{
if(a[flag]>a[2*flag])
{
t=2*flag;
}
if(flag*2+1>=k)
{
if(a[t]>a[2*flag+1])
{
t=2*flag+1;
}
}
if(t==flag)
break;
else
{
swap(a[t],a[flag]);
flag=t;
}
}
}
}
}
cout<<a[1]<<endl;
}
测试结果