从上面找到矢量中最接近的值的优雅方式

时间:2011-12-27 17:47:11

标签: c++ algorithm stl

我需要一个带矢量(假设为已排序)和一个值的函数,并返回大于小于或等于该值的最接近的数字 数字,最好使用STL的算法。我使用std :: lower_bound()提出了一个解决方案,但它似乎很丑陋和丑陋:

struct ClosestCmp {
    bool operator()(const int & x, const int & y) { return x > y; }
};

// vec is assumed to be sorted
int closest(const std::vector<int> & vec, int value)
{
    std::vector<int>::const_reverse_iterator cri =
        std::lower_bound(vec.rbegin(), vec.rend(), value, ClosestCmp());
    if (cri != vec.rend()) {
        return *cri;
    }
    return -1;
}

// ...
vec.push_back(1);
vec.push_back(2);
vec.push_back(4);
vec.push_back(5);
std::cout << closest(vec, 2) << "\n"; // Should ouput "2"
std::cout << closest(vec, 3) << "\n"; // Should ouput "2"
std::cout << closest(vec, 4) << "\n"; // Should ouput "4"

任何人都可以建议一种更优雅的方式,可能使用STL算法而不需要比较函数或反向迭代器吗?我已经查看了STL,但是找不到比这更好的解决方案了。

5 个答案:

答案 0 :(得分:16)

提醒:

  • std::lower_bound:返回不比较少的第一个值
  • std::upper_bound:返回严格比较的第一个值

根据您的描述,std::lower_bound已经看起来非常合适,有什么问题:

int closest(std::vector<int> const& vec, int value) {
    auto const it = std::lower_bound(vec.begin(), vec.end(), value);
    if (it == vec.end()) { return -1; }

    return *it;
}

用作:

int main() {
    std::vector<int> vec;
    vec.push_back(2);
    vec.push_back(4);

    std::cout << closest(vec, 2) << "\n";
    std::cout << closest(vec, 3) << "\n";
    std::cout << closest(vec, 4) << "\n";
}

输出:

2
4
4

答案 1 :(得分:5)

您只能将std::lower_boundstd::upper_bound与二进制谓词一起使用,该二进制谓词与容器的顺序相匹配。因此,您无法按<排序,然后使用其他二元谓词(例如<=>)。所以你的“kludge”实际上是正确的事情。反向排序的向量是您要用于查找小于或等于该值的元素的排序条件。 (否则,如果您实际搜索的值大于或等于,则可以使用std::lower_bound。)

答案 2 :(得分:3)

需要C ++ 11:

hi

答案 3 :(得分:2)

这样的东西可行......取最小的最接近的值:

可以作为模板或其他东西,而不是那些了解模板编程的人。 http://ideone.com/ff46ax

#include <iostream>
#include <vector>
#include <map>
#include <stdlib.h>

int main()
{
    int comparevalue = 3;
    typedef std::vector<int> intvec;
    intvec myvec;

    myvec.push_back(1);
    myvec.push_back(2);
    myvec.push_back(4);
    myvec.push_back(5);
    myvec.push_back(6);
    myvec.push_back(7);

    typedef std::map<int, int> intmap;
    intmap mymap;

    for (intvec::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr)
        mymap.insert(std::make_pair(abs(*itr-comparevalue), *itr));

    std::cout << "difference:" << mymap.begin()->first << "\n";
    std::cout << "value:" << mymap.begin()->second;
    return 0;
}

答案 4 :(得分:0)

对于小于或等于的最大者,可以使用此功能

int closest(std::vector<int> const& vec, int value) {
    auto const it = std::lower_bound(vec.begin(), vec.end(), value);
    if (it == vec.begin()) { return -1; }
    else return *(it - 1);
}