可以用容量为K的最小堆来存储最大的K个数。最小堆的堆顶就是最大K个数中最小的一个,即第K大的数。每次新考虑一个数X,如果X比堆顶的元素Y小,则不需要改变原来的堆,如果比堆顶元素大,那么用X替换堆顶的元素Y。在X替换堆顶元素Y之后,X可能破坏最小堆的结构,需要更新堆来维持堆的性质。更新过程花费的时间复杂度为O(log2K).
#include<iostream>
using namespace std;
void maxHeap(int *a,int i,int heapSize)
{
int l = 2*i;
int r = 2*i+1;
int maximum=0;
if(l<=heapSize&&a[l-1]>a[i-1]) //左孩子大于父节点
maximum = l;
else
maximum = i;
if(r<=heapSize&&a[r-1]>a[maximum-1]) //若右孩子比左孩子、父节点都大
maximum = r;
if(maximum!=i)
{
swap(a[i-1],a[maximum-1]);
maxHeap(a,maximum,heapSize); //检测孩子树
}
}
void buildMaxHeap(int *a,int heapSize)
{
for(int i=heapSize/2;i>=1;--i) //从heapSize/2开始建堆
maxHeap(a,i,heapSize);
}
void heapSort(int *a,int heapSize)
{
buildMaxHeap(a,heapSize); //建堆
for(int i=heapSize;i>=2;--i)
{
swap(a[0],a[i-1]);
--heapSize;
maxHeap(a,1,heapSize); //调整
}
}
int K_max(int *temp,int *a,int K,int num)
{
for(int i=K;i<num;++i)
{
if(a[i]>temp[0])
{
temp[0] = a[i];
int p = 0;
while(p < K)
{
int q = 2*p+1;
if(q>=K) //已到叶节点
break;
if(q<K-1 && temp[q+1]<temp[q])
++q;
if(temp[q] < temp[p])
{
swap(temp[q],temp[p]);
p = q;
}
else
break;
}
}
}
return temp[0];
}
void print(int *a,int num)
{
for(int i=0;i<num;++i)
cout<<a[i]<<ends;
}
int main()
{
int a[]={16,4,10,14,7,9,3,2,8,1,5,0,20};
int num = sizeof(a)/sizeof(a[0]);
int K;
cout<<"Please input the K(the number of K-max):";
cin>>K;
int *temp = new int[K] ;
for(int i=0;i<K;++i)
temp[i] = a[i];
heapSort(temp,K);
//heapSort(a,num);
print(temp,K);
//print(a,num);
cout<<endl<<K_max(temp,a,K,num)<<endl;
//print(temp,K);
return 0;
}
完成后时间复杂度为O(N*log2K).