Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用std::equal_range在某些范围内搜索向量_C++_Search_Stl - Fatal编程技术网

C++ 使用std::equal_range在某些范围内搜索向量

C++ 使用std::equal_range在某些范围内搜索向量,c++,search,stl,C++,Search,Stl,我有一个std::vector,元素是成对的,需要找到第一个分量在某些范围内的所有元素,例如,要找到所有元素,比如abs(第一个分量的值-参考)我认为你应该在函数comp()中使用fabs而不是abs相等范围需要排序范围 比较函数隐含的顺序与将范围排序到的顺序不匹配,因此对equal\u range的调用具有未定义的行为 例如,假设您的列表包含{.5,0},{.6,0}(这些已排序),然后您将std::bind(comp({.5,5},_1))应用于每个元素 comp({.5,5},{.5,0}

我有一个std::vector,元素是成对的,需要找到第一个分量在某些范围内的所有元素,例如,要找到所有元素,比如abs(第一个分量的值-参考)我认为你应该在函数
comp()中使用
fabs
而不是
abs

相等范围
需要排序范围

比较函数隐含的顺序与将范围排序到的顺序不匹配,因此对
equal\u range
的调用具有未定义的行为

例如,假设您的列表包含
{.5,0},{.6,0}
(这些已排序),然后您将
std::bind(comp({.5,5},_1))
应用于每个元素

comp({.5,5},{.5,0})
将返回true

comp({.5,5},{.6,0})
将返回false

您的排序顺序是:“
.5
小于
.6
”,但同时您的
comp
函数是“
.6
小于
.5
”(因为存在一个小于
.5
但不小于
.6
)的值。这是矛盾的,也是你问题的原因


要实际查找所有元素,例如
std::bind(comp({.5,.5},_1))
返回true,您可以使用
std::copy_if(data.begin()、data.end()、一些输出迭代器、std::bind(comp(ref,std::placeholders::_1))
(尽管有多种不同的方法,具体取决于您的需要).

您的比较函数不满足严格弱排序的要求,即对于两个元素,例如a和b,如果
comp(a,b)=true
,则
comp(b,a)
应为
false

你可能想要更像这样的东西:

struct Comp {
  double target;
  bool operator()(const pair<double, double>& lhs,
                  const pair<double, double>& rhs) const {
    return abs(lhs.first - target) < abs(rhs.first - target);
  }
};

vector< pair<double, double> > data;
data.push_back(make_pair(0.1, 1.0));
data.push_back(make_pair(0.15, 1.2));
data.push_back(make_pair(0.189, 2.1));
data.push_back(make_pair(0.19, -2.1));
data.push_back(make_pair(0.192, 3.1));
data.push_back(make_pair(0.2, 0.1));
data.push_back(make_pair(0.205, 0.1));
data.push_back(make_pair(0.205, 0.0));
data.push_back(make_pair(0.206, 12.1));
data.push_back(make_pair(0.21, -12.9));
data.push_back(make_pair(0.3, 3.4));
data.push_back(make_pair(0.5, 7.5));
// We *must* sort the vector using the same comparison function that we're
// about to use to get the lower and upper bounds
Comp comp;
comp.target = 0.2;
sort(data.begin(), data.end(), comp);

// Get the lower bound
pair<double, double> low(make_pair(comp.target, 0.0));
vector< pair<double, double> >::iterator lower =
    lower_bound(data.begin(), data.end(), low, comp);

// Get the upper bound
pair<double, double> up(make_pair(comp.target + 0.01, 0.0));
// N.B. use "lower_bound" here to get upper bound of target + 0.01 exclusive.
//      If we want to include target + 0.01, use "upper_bound"
vector< pair<double, double> >::iterator upper =
    lower_bound(data.begin(), data.end(), up, comp);

for_each(lower, upper, [](const pair<double, double> &data_point) {
  cout << data_point.first << "\t" << data_point.second << "\n";
});

未能初始化
a
b
不会随机初始化它们-读取未初始化的值会调用未定义的行为。嗨,Mankarse,a和b是随机初始化的,我只是懒得在那里显示代码。对不起。无论如何,因为向量中只有10个元素,我把它们打印出来,然后一个一个地比较,但是,由于反馈,搜索算法还是不起作用。但是abs的原型在我的编译器中接受双值并返回双精度。无论如何,我也尝试了fabs,但不起作用,但是abs是一个模板函数,它接受双类型参数,这让人困惑。那么,有没有办法修改代码以找到所需的元素?@user1285419:您可以使用
std::partition(data.begin(),data.end(),std::bind(comp(ref,std::placeholders::_1))
。如果这样做,则不需要对向量进行排序。您需要的结果将介于
data.begin()
std::partition
的返回值之间。谢谢。使用std::partition可以工作,但速度太慢了。在我的例子中,向量包含200000多个元素,搜索过程将重复多次。@user1285419:
std::partition
具有线性时间复杂度。它渐进地优于您使用的“排序-然后-相等范围”方法。它也是渐近最优的(每个元素必须至少访问一次才能找到满足谓词的所有元素)。(也就是说,可能还有更好的方法来实现您正朝着的实际最终结果)。我现在使用的方法只是首先对向量进行排序,然后通过循环搜索满足要求的元素,因为向量已排序,当我们到达大于参考差的元素时,打破循环。我不知道这是否好,但将其与std::partition进行比较,似乎分区所需的时间是std::partition的两倍。但无论如何,我的路还是太慢了,我仍然在寻找更快的路。谢谢弗雷泽。我为以下数据集(0.1,1.0),(0.15,1.2),(0.189,2.1),(0.19,-2.1),(0.192,3.1),(0.2,0.1),(0.205,0.1),(0.205,0.0),(0.206,12.1),(0.21,-12.9),(0.3,3.4),(0.5,7.5)尝试了您的代码。我正在搜索x分量在0.19到0.21之间的所有点,即目标=0.2,它假定给我以下点,但它显示的结果实际上是空的(0.189,2.1),(0.19,-2.1),(0.192,3.1),(0.2,0.1),(0.205,0.1),(0.205,0.0),(0.206,12.1),(0.21,-12.9)。我编辑了答案,以匹配上面的数据。这对我来说很好。(0.189,2.1)不应包含在结果中,因为它与目标值的距离大于0.01。(0.19,-2.1)被排除,因为您指定了
<0.01
,而不是

struct Comp {
  double target;
  bool operator()(const pair<double, double>& lhs,
                  const pair<double, double>& rhs) const {
    return abs(lhs.first - target) < abs(rhs.first - target);
  }
};

vector< pair<double, double> > data;
data.push_back(make_pair(0.1, 1.0));
data.push_back(make_pair(0.15, 1.2));
data.push_back(make_pair(0.189, 2.1));
data.push_back(make_pair(0.19, -2.1));
data.push_back(make_pair(0.192, 3.1));
data.push_back(make_pair(0.2, 0.1));
data.push_back(make_pair(0.205, 0.1));
data.push_back(make_pair(0.205, 0.0));
data.push_back(make_pair(0.206, 12.1));
data.push_back(make_pair(0.21, -12.9));
data.push_back(make_pair(0.3, 3.4));
data.push_back(make_pair(0.5, 7.5));
// We *must* sort the vector using the same comparison function that we're
// about to use to get the lower and upper bounds
Comp comp;
comp.target = 0.2;
sort(data.begin(), data.end(), comp);

// Get the lower bound
pair<double, double> low(make_pair(comp.target, 0.0));
vector< pair<double, double> >::iterator lower =
    lower_bound(data.begin(), data.end(), low, comp);

// Get the upper bound
pair<double, double> up(make_pair(comp.target + 0.01, 0.0));
// N.B. use "lower_bound" here to get upper bound of target + 0.01 exclusive.
//      If we want to include target + 0.01, use "upper_bound"
vector< pair<double, double> >::iterator upper =
    lower_bound(data.begin(), data.end(), up, comp);

for_each(lower, upper, [](const pair<double, double> &data_point) {
  cout << data_point.first << "\t" << data_point.second << "\n";
});
0.2     0.1
0.205   0.1
0.205   0
0.206   12.1
0.192   3.1
0.21    -12.9