在查找过程中,使用随机数生成器随机生成一个随机数最为一个下标,根据该下标将数组分为两部分,前一部分元素均是小于下标对应元素,后一部分均是大于下标对应元素。如果下标对应元素刚好是第k大元素这查找结束,否则根据与k大小的比较结果,选择前一部分或者后一部分进行查找。
例如:假设数组A原始数据为3 5 12 8 2需要查找第三大元素。 随机数生成器生成的数位1,将小于A[1]的元素移动到前面,大于A[1]的元素移动到右面,移动后 数组为3 2 5 8 12,此时5即为查找元素,查找结束。如果查找第二大的元素,则在3 2 中继续查找,查找第四大的元素则在8 12 中继续查找。
#include <iostream>
#include <vector>
using namespace std;
//根据随机数将数组随机分为两部分前一部分为小与随机数对应下标的元素
//后一部分为大于随机数对应下标元素,返回值为随机数对应下标元素排序后的位置
template <typename T>
int random_partition(vector<T>& temp,const size_t& begin,const size_t& end)
{
if (begin == end)//数组含有一个元素,直接返回
return 1;
int rad = (int)(begin + rand()/RAND_MAX*(end - begin));//生成[begin,end]间的一个随机数
swap(temp[rad],temp[end]);
int minloc = -1;//minloc保存目前小于随机数对应元素的最大下标
for (int i = 0;i < end;i++)
{
if (temp[i] < temp[end])//将小于随机数元素的数移动到前面
{
minloc++;
swap(temp[minloc],temp[i]);
}
}
swap(temp[++minloc],temp[end]);
return minloc+1;//返回随机数对应元素的排序大小
}
template<typename T>
T random_select(vector<T>& number,const size_t& begin,const size_t& end,const int& k)
{
if (k <= 0 || k > end - begin + 1)
{
return -1;
}
int rand_loc = random_partition(number,begin,end);
if (k == rand_loc)//找到,返回
return number[rand_loc-1];
if (rand_loc > k)//找到的大于需要的元素,在前一部分继续查找
return random_select(number,begin,rand_loc-2,k);
else//小于所需元素,在后一部分继续查找
return random_select(number,rand_loc,end,k-rand_loc);
}
int main()
{
vector<int> number;
number.push_back(3);
number.push_back(5);
number.push_back(12);
number.push_back(8);
number.push_back(2);
cout << random_select(number,0,4,2);
return 0;
}