寻找第K大的数

来源:互联网 发布:简单的递归算法java 编辑:程序博客网 时间:2024/05/01 07:06

可以用容量为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;elsemaximum = 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;}elsebreak;}}}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).

原创粉丝点击