我有一个矢量示例矢量myVec;
例如,我的矢量中有100个元素。现在我想迭代100个元素并找到向量中可能的10个最小元素。//执行此操作的一种方法是使用sort algoritm按顺序对矢量项进行排序,并获取前10项。然后在这里我必须创建另一个矢量来存储原始和排序的矢量。这里的原始程序需要知道向量中每个10的sortest值的行号 - 这是我程序中的那个。
但是现在我需要一个最简单的for循环或while语句来找到向量中的10个最小值而不进行排序?。
答案 0 :(得分:0)
检查此示例:
// partial_sort example
#include <iostream> // std::cout
#include <algorithm> // std::partial_sort
#include <vector> // std::vector
int main () {
int myints[] = {9,8,7,6,5,4,3,2,1};
std::vector<int> myvector (myints, myints+9);
// using default comparison (operator <):
std::partial_sort (myvector.begin(), myvector.begin()+5, myvector.end());
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
输出:
myvector contains: 1 2 3 4 5 9 8 7 6
它使用std::partial_sort(如Jarod42所说),它对第一个n
值(在您的情况下为10)进行排序,同时将其他值保留为任意顺序。现在你可以修改它来满足你的需求。
答案 1 :(得分:0)
实际上,鉴于您只需要知道10个最小的项目(并且不需要按顺序排列这10个项目),您可以使用std::nth_element
代替std::partial_sort
。这正是你所要求的,没有什么额外的,所以它很有可能提高效率。
就避免复制输入而言,您可以创建一个索引向量,用于索引到原始数组中,并对索引而不是原始数组进行操作。
一般的想法看起来像这样:
std::vector<foo> input;
// ...
// This is our index. It'll be filled with 0..I (where I = size of input).
std::vector<std::size_t> index(input.size());
std::iota(index.begin(), index.end(), 0);
// This is the number of smallest items we need to find:
const int N = 10;
if (index.size() <= N) // if we have fewer elements, do nothing.
return;
// sort our index according to the values in the input:
std::nth_element(index.begin(), index.begin() + N, index.end(),
[&input](size_t a, size_t b) { return input[a] < input[b]; });
// write out the N smallest items of the input.
for (int i = 0; i < N; i++)
std::cout << input[index[i]] << "\t";
当然,您可以使用指向原始项目而不是索引的指针向量,但是您说您需要“行号”,因此我编写了代码来提供完全相同的内容。
答案 2 :(得分:0)
如果您需要自己编写代码,请使用快速选择来查找第10个最小元素。这会将数组分成几个部分,左边是最小的,第9个最小但是没有排序,第10个最小作为枢轴,右边是元素&gt; =第10个最小元素。维基文章:
答案 3 :(得分:0)
通常,我建议您使用其他答案中建议的标准库sort,partial_sort,nth_element等。
但是,找到min并不难,避免排序并避免重复矢量,
AND
如果您在要求时确实是指它:
我需要一个最简单的for循环或while语句来查找10 矢量中的最小值没有排序?。
这是一种方法:(参见下面的评论“找到10个最小值”)
#include <iomanip>
#include <iostream>
#include <vector>
#include <chrono>
#include <algorithm> // shuffle
typedef std::vector< int > IntVec;
typedef std::vector< size_t > IndxVec;
const size_t SMALLEST_10 = 10;
void myVecShow(IntVec& intVec, const std::string label); // below
// ///////////////////////////////////////////////////////
size_t findIndxOfMinValue(const IntVec& intVec)
{
size_t minIndx = 0; // search from beginning
for (size_t j = 0;
j < intVec.size(); // compare each
++j)
{
if(intVec[j] < intVec[minIndx])
minIndx = j; // capture smallest
}
return(minIndx);
}
// ///////////////////////////////////////////////////////
int t258()
{
IntVec myVec;
{
// fill myVec
for (int i=0; i<100; ++i)
myVec.push_back(100-i); // "my vector for instance has 100 elements in it."
//myVecShow(myVec, "\n unshuffled values: ");
// shuffle myVec
time_t seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle (myVec.begin(), myVec.end(), std::default_random_engine(seed));
myVecShow(myVec, "\n Values: ");
}
IndxVec indxVec; // to be filled with index of the smallest elements
indxVec.reserve(SMALLEST_10);
IntVec origVal; // capture original values of smallest elements
origVal.reserve(SMALLEST_10);
// ///////////////////////////////////////////////////////
// find 10 smallest values
{
for (size_t i=0; i<SMALLEST_10; ++i)
{
size_t minValIndx = findIndxOfMinValue(myVec);
indxVec.push_back (minValIndx); // capture index
origVal.push_back (myVec[minValIndx]); // capture value at index
myVec[minValIndx] = std::numeric_limits<int>::max(); // mark min value (so its no longer min)
}
std::cout << std::endl;
}
// restore original values prior to report
for (size_t i=0; i<indxVec.size(); ++i)
{
size_t indx = indxVec[i];
myVec [indx] = origVal[i];
}
// ///////////////////////////////////////////////////////
// report results
std::cout << "\nSmallest 10 elements: " << std::endl;
std::cout << " indx value" << std::endl;
for (size_t i=0; i<indxVec.size(); ++i)
{
size_t indx = indxVec[i];
std::cout << "myVec[" << std::setw(2) << indx
<< "] = " << std::setw(3) << myVec[indx]
<< std::endl;;
}
std::cout << std::endl;
return(0);
} // int t258(void)
// ///////////////////////////////////////////////////////
void myVecShow(IntVec& intVec, const std::string label)
{
std::cout << label << std::endl;
size_t j = intVec.size() - 1;
// header:
{
std::cout << " ";
for (size_t i=0; i<SMALLEST_10; ++i) std::cout << std::setw(3) << i << " ";
std::cout << std::endl;
}
std::cout << std::setw(3) << 0 << ": ";
for (size_t i=0; i<intVec.size(); ++i)
{
std::cout << std::setw(3) << intVec[i] << " ";
if ((i < j) && (9 == (i % 10)))
{
size_t row = 1 + (i / 10);
std::cout << std::endl << std::setw(3) << row << ": ";
}
}
std::cout << std::endl;
}
结果:(随机洗牌)
Values:
0 1 2 3 4 5 6 7 8 9
0: 50 85 6 62 48 34 40 73 86 11
1: 94 58 46 96 66 56 42 15 25 13
2: 92 30 7 35 65 37 5 69 90 68
3: 100 3 2 87 21 93 43 99 10 98
4: 44 24 70 41 59 95 72 49 78 81
5: 4 23 47 51 36 54 12 67 91 14
6: 53 97 71 52 77 27 20 29 76 83
7: 80 28 17 38 32 16 39 9 74 18
8: 84 31 61 45 8 33 82 55 63 89
9: 60 26 88 79 1 19 57 75 64 22
Smallest 10 elements:
indx value
myVec[94] = 1
myVec[32] = 2
myVec[31] = 3
myVec[50] = 4
myVec[26] = 5
myVec[ 2] = 6
myVec[22] = 7
myVec[84] = 8
myVec[77] = 9
myVec[38] = 10
更新 - 当最小的10中的值重复时会发生什么:
我添加了
myVec[6] = 7;
重新运行代码(因此,这是一个不同的随机shuffle),输出是:
Smallest 10 elements:
indx value
myVec[ 7] = 0
myVec[78] = 1
myVec[83] = 2
myVec[79] = 3
myVec[11] = 4
myVec[87] = 5
myVec[12] = 7
myVec[67] = 7
myVec[42] = 8
myVec[51] = 9
更新 - 我们如何修改此代码以显示最小的10个唯一值的索引
注意:未运行测试,并且此第一次尝试代码(可能)无法正确处理少于10个唯一值的100元素数组
// find 10 smallest **unique** values
{
for (size_t i=0; i<SMALLEST_10; ++i)
{
size_t minValIndx = findIndxOfMinValue(myVec);
indxVec.push_back (minValIndx); // capture index
origVal.push_back (myVec[minValIndx]);
myVec[minValIndx] = std::numeric_limits<int>::max();
// now hide any duplicate of this minValue,
for (size_t j=0; j<myVec.size(); ++j) // search all
{
if(myVec[j] == origVal.back())
{
indxVec.push_back (j); // capture index
origVal.push_back (myVec[j]);
myVec[minValIndx] = std::numeric_limits<int>::max();
}
}
}
std::cout << std::endl;
}