方法1:
对这N个数进行排序,然后找出第k个最大者。
这是最容易想到的也是最容易写出来的方法,但这种方法效率很低,当N比较大的时候不适合用。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
typedef vector<int> Vect;
typedef vector<int>::iterator Iter;
void sort(Vect &ivec); //选择排序
int search(const Vect &ivec, int k); //查找第k大的元素
int main(void)
{
int data[] = {4,6,3,7,2,8,1,9,0,5};
Vect ivec(data, data + sizeof(data)/sizeof(int));
sort(ivec);
cout << search(ivec, 10) << endl;
cin.get();
return 0;
}
void sort(Vect &ivec)//选择排序
{
Iter iter_i, iter_j;
for(iter_i = ivec.begin(); iter_i != ivec.end()-1; ++iter_i)
{
Iter iter_k = iter_i;
for(iter_j = iter_i+1; iter_j != ivec.end(); ++iter_j)
{
if(*iter_j > *iter_k)//升序排序
{
iter_k = iter_j;
}
}
if(iter_i != iter_k)//移动元素
{
int temp = *iter_i;
*iter_i = *iter_k;
*iter_k = temp;
}
}
}
int search(const Vect &ivec, int k)//查找第k大的元素
{
if(k > ivec.size())
{
cerr << "wrong" << endl;
}
else
{
return ivec.at(k-1);
}
}
方法2:
对方法1进行修改,可以提高程序运行的效率。可以先读入k个元素并对其排序,接着将剩余的元素逐个读入。当读入一个新元素时,如果小于数组中的第k个元素,则忽略之,否则插入数组,将原来的第k个元素挤掉。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
typedef vector<int> Vect;
typedef vector<int>::iterator Iter;
void sort(Vect &ivec, Vect::size_type k); //对前k个元素进行选择排序
int search(Vect &ivec, Vect::size_type k); //查找第k大的元素
int main(void)
{
int data[] = {4,6,3,7,2,8,1,9,0,5};
Vect ivec(data, data + sizeof(data)/sizeof(int));
cout << search(ivec, 5) << endl;
cin.get();
return 0;
}
void sort(Vect &ivec, Vect::size_type k)//对前k个元素进行选择排序
{
Iter iter_i, iter_j;
for(iter_i = ivec.begin(); iter_i != ivec.begin() + k -1; ++iter_i)
{
Iter iter_k = iter_i;
for(iter_j = iter_i+1; iter_j != ivec.begin() + k; ++iter_j)
{
if(*iter_j > *iter_k)//升序排序
{
iter_k = iter_j;
}
}
if(iter_i != iter_k)//移动元素
{
int temp = *iter_i;
*iter_i = *iter_k;
*iter_k = temp;
}
}
}
int search(Vect &ivec, Vect::size_type k)//查找第k大的元素
{
if(k > ivec.size())
{
cerr << "wrong" << endl;
return -1; //标记错误信息,如果输入序列中有负数,则不能用-1,这里测试数据都是正数
}
sort(ivec, k);
Vect::size_type flag = k;
while(flag != ivec.size())
{
Iter iter = ivec.begin() + k-1;//标记第k个元素
if(*iter < ivec.at(flag)) //如果后面的元素大于第k个元素,则按升序插入并挤掉第k个元素
{
while(iter != ivec.begin() && *(iter-1) < ivec.at(flag))//将所有比当前元素小的元素都后移一个位置
{
*iter = *(iter-1);
--iter;
}
*iter = ivec.at(flag);//将当前元素插入
}
++flag; //处理下一个元素
}
return ivec.at(k-1);
}
第三种方法:
如果元素个数是1000万呢,这样用以上两种方法都可以处理,但都需要很长的时间,这就需要改进算法了。先开辟一个很大的数组,其最大下标要大于输入元素中的最大元素,然后将输入的元素按下标存储,输入完以后遍历数组就可以得到第k大的元素了。
代码如下:
#include <iostream>
#include <vector>
using namespace std;
typedef vector<int> Vect;
typedef vector<int>::iterator Iter;
int main(void)
{
Vect ivec(10000, 0);
int n, k;
cout << "请输入要输入元素的个数,以及要求第k大元素的k值:";
cin >> n >> k;
cout << "请输入元素:";
for(int i=0; i<n; ++i)
{
int temp;
cin >> temp;
++ivec.at(temp);
}
for(Vect::size_type i = ivec.size()-1; i >= 0; --i)
{
if(k > 0 && ivec[i] != 0)
{
k -= ivec[i];
}
if(k <= 0)
{
cout << i << endl;
break;
}
}
cin.get();
return 0;
}