其实按照上一篇文章的思路,可以根据快排来计算第k大的数。
但会修改数组中的数据,所以这里有新的不修改数据的思路:
1、用multiset实现自动排序,大小为k,每个数与set中最大的数比较,如果小于则替换。
2、可以用最大堆来实现,方法类似上面的。关键是看代码注释在下面。
时间复杂度为:
#include<iostream>
#include<vector>
#include<set>
using namespace std;
int numbers[100];
//从vector获取数据
void getnumbers(vector<int>& numbers){
numbers.clear();
int x;
printf("输入数据:\n");
scanf("%d",&x);
while(x!=-1){
numbers.push_back(x);
scanf("%d",&x);
}
}
//用模板找出第k个数
void templatefindk(const vector<int>& numbers){
int k;
printf("输入要查找的数\n");
scanf("%d",&k);
multiset<int,greater<int>> Intset;
vector<int>::const_iterator iter = numbers.begin();
//从大到小排序
multiset<int,greater<int>>::iterator intiter;
while(iter != numbers.end()){
if(Intset.size()<k)
Intset.insert(*iter);
else{
intiter = Intset.begin();
if(*iter<*intiter){
Intset.erase(intiter);
Intset.insert(*iter);
}
}
++iter;
}
intiter = Intset.begin();
printf("第%d大的数为%d\n",k,*intiter);
}
//numbers[beg+1]到numbers[len]为最大堆,将numbers[beg]插入其中
void heapdown(int *heap,int beg,int len){
int temp = heap[beg];
int i = 2*beg+1;
while(i<=len){
if(i+1 <=len && heap[i]<heap[i+1])
i = i+1;
if(heap[i]<=heap[beg])
break;
heap[beg] = heap[i];
beg = i;
i = 2*beg+1;
}
heap[beg] = temp;
}
//建立最大堆
void buildheap(int *heap,int len){
for(int beg = len/2-1;beg >=0;beg--)
heapdown(heap,beg,len);
}
//用堆找第k大的数
void heapfindk(){
int len =0,x,k;
printf("输入数组\n");
scanf("%d",&x);
while(x!= -1){
numbers[len++] = x;
scanf("%d",&x);
}
printf("输入要查找的数位置\n");
scanf("%d",&k);
int *heap = (int *)malloc(sizeof(int)*k);
int i =0;
while(i<k){
heap[i] = numbers[i++];
}
//前k个数建堆
buildheap(heap,k-1);
while(i<=len){
if(numbers[i++]<heap[0])
heapdown(heap,0,k-1);
}
printf("第%d大的数为%d\n",k,heap[0]);
}
int main(){
vector<int> numbers;
printf("用模板找\n");
getnumbers(numbers);
templatefindk(numbers);
//
printf("用堆来找\n");
heapfindk();
system("PAUSE");
return 0;
}