我刚刚第一次接触到std :: vector,现在我想改变使用普通C风格数组的坏习惯。我发现std :: list是排序时使用的容器。但是,我不是100%如何完成以下任务:
我正在做一些计算,其结果取决于两个指数(i和j)。最后,我只对100个最小的结果感兴趣(不一定是100,但肯定比我的计算值总数小得多,m * n在下面的代码中)。
const int L = 100;
int i_list[L];
int j_list[L];
double value_list[L];
for (int i=0;i<m;i++){
for (int j=0;j<n;j++){
double x = doSomeCalculations(i,j);
insertTheValueAndIndices(i,j,x,i_list,j_list,value_list);
}
}
完成后,value_list应包含100个最小值(递增顺序)和i_list / j_list相应的索引。我有&#34; insertValuesAndIndices()&#34;的工作版本,但在那里我使用普通数组和插入新值的最低效方法。在写作的过程中,我意识到我实际上有两个截然不同的问题:
计算值的数量(m * n)远远大于我想要保留在列表中的数量,因此简单地保留所有值并且最后只排序一次并不是真正的选择。另一方面,我最终只需要正确的结果,所以也许有一种方法只对列表进行一次排序。有没有&#34;标准&#34;这种排序聪明有效的方法呢?
即使我可以存储所有结果并在之后进行排序,我也不确定如何使用std :: list.sort()以正确的顺序获取索引数组。我想到的是定义一些包含结果和两个索引的类,将这些元素放在一个列表中,然后使用一个只检查值来进行排序的比较器。但是,也许有一种更简单的方法可以做同样的事情吗?
干杯&amp;提前致谢
答案 0 :(得分:5)
首先,您可能不想要std::list
,但需要std::vector
。
然后使用std::lower_bound
查找要插入的位置,以及是否插入
结果向量包含多于元素的数量
你感兴趣,std::vector<>::pop_back
要摆脱
额外的一个。
答案 1 :(得分:0)
感谢您的评论。由于我的帖子没有陈述一个明确定义的问题,但它反而证明了我对如何解决我的问题的无知;),我想发布我的结论和一个有效的例子......
首先,感谢澄清,&#34; std :: list是排序时使用的容器&#34; 不是真的。正如所指出的,通过James Kanze,std :: vector也能完成这项工作。其次,我真的没有&#34;排序&#34;如果我只是&#34;插入&#34;在正确的地方新的价值观。此外,没有人反对我的想法如何使索引也排序,这是我的解决方案:
#include <cfloat>
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
struct MyValue{
MyValue(double v,int f,int s):value(v),first(f),second(s){}
double value;
int first;
int second;
};
bool compareValues(const MyValue a,const MyValue b){return a.value < b.value;}
void insertMyValue(std::vector<MyValue>* v,MyValue x,int maxSize){
v->insert(std::lower_bound(v->begin(),v->end(),x,compareValues),x);
if (v->size()>maxSize){v->erase(v->end()-1);}
}
void main(){
const int imax = 10;
const int jmax = 10;
const int Nmax = 30;
std::vector<MyValue> results;
results.reserve(Nmax+1);
// Fill the vector
for (int i=0;i<imax;i++){
for (int j=0;j<jmax;j++){
double result = i*(j+0.1);
insertMyValue(&results,MyValue(result,i,j),Nmax);
}
}
// Print it
for (std::vector<MyValue>::iterator it = results.begin();it<results.end();it++){
cout << (*it).first << " " << (*it).second << " " << (*it).value << endl;
}
}
答案 2 :(得分:0)
排序是一个坏主意。
而是使用std::vector<int> buffer(count);
来存储std::make_heap
。
然后做:
template<class T>
void add_element( std::vector<T>& heap, T element, size_t size ) {
heap.push_back(element);
std::push_heap(heap.begin(), heap.end());
while (heap.size() > size) {
std::pop_heap(heap.begin(), heap.end());
heap.pop_back();
}
}
以vector
形式获取堆(空vector
是堆),并添加一个元素,然后弹出超过堆限制的任何元素。
这适用于T
的任何operator<
。还有push_heap
和pop_heap
的自定义比较器版本。