在向量中查找最小项目的列表
finding list of minimum items in a vector
我有一个向量示例向量myVec;
例如,我的向量中有100个元素。现在我想遍历100个元素,找到向量中可能的10个最小元素。
//一种方法是使用排序算法按递增顺序对矢量项目进行排序,并获得前10个项目。然后在这里,我必须创建另一个向量来存储原始和排序的向量。这里的原始程序需要知道向量中排序值的每10个的行号——这在我的程序中。
但现在我需要一个最简单的for循环或while语句来在不排序的情况下找到向量中的10个最小值?。
通常,我建议您使用其他答案中建议的std库排序、partial_sort、nth_element等。
然而,找到一个最小值并避免排序和避免复制向量并不困难,
和
以防你要求时真的是认真的
我需要一个最简单的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;
重新运行代码(所以,这是一个不同的随机洗牌),输出为:
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;
}
检查此示例:
// 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)进行排序,同时将其他值按任意顺序保留。现在,您一定可以修改它以满足您的需求。
实际上,假设您只需要知道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";
当然,你可以使用指向原始项的指针向量,而不是索引,但你说你需要"行号",所以我编写了代码来提供这一点。
如果您需要自己编写代码,请使用快速选择来查找第10个最小的元素。这将把数组分成几个部分,左边是最小到第九小的,但没有排序,第十小的作为轴心,右边是元素>=第十小元素。Wiki文章:
http://en.wikipedia.org/wiki/Quickselect
- 如何维护资源管理器项目视图中当前可见的项目列表
- 在给定的项目列表上实现搜索?
- 在修改项目列表时,请防止可编辑的Qcombobox选择更改
- 发送 QML 项目列表C++类连接到 QML :M16 错误
- 当SLIST_ENTRY不是项目列表的第一个成员时,使用单向链表
- 项目列表中的组合
- 将项目小部件宽度(列表内容)调整为父QListWidget宽度
- C ++ win 32,我想将项目列表添加到组合框中.我该怎么做
- 当试图在C++eclipse工作区中导出一个团队集(5个项目)时,项目列表是空的
- 随机化项目列表并将其输出到文本文件
- 关于密码学的小项目
- 获取QGuiApplication的小部件列表
- Eclipse CDT 自动更新/同步项目列表(以方便"refresh"相关项目集)
- 在每次迭代中以不同顺序循环遍历项目列表
- “添加到项目列表”是灰色的Qt项目管理对话框
- 从 std::vector<std::vector 中删除任意项目列表<T> >
- QT:来自多个旋转框的项目列表
- QComboBox动态项目列表
- QComboBox 不显示其项目列表
- 在浏览项目列表时保存多个项目的数据