C++ 具有不同==和<;算子语义

C++ 具有不同==和<;算子语义,c++,stl,set,C++,Stl,Set,我使用的是一个非常简单的结构,映射,定义如下: struct mapping{ int code; string label; bool operator<(const mapping& map) const { return code < map.code; } bool operator==(const mapping& map) const { return label.compare(

我使用的是一个非常简单的结构,映射,定义如下:

struct mapping{
    int code;
    string label;

    bool operator<(const mapping& map) const {
        return code < map.code;
    }

    bool operator==(const mapping& map) const {
        return label.compare(map.label) == 0 ;
    }
};
我如何解决这个问题,并设法用非常不同的语义处理操作符<和==呢?理想情况下,我希望避免在整个集合上迭代以查找具有相同标签的映射。这种策略的复杂性是O(n),在我的应用程序中,n可能相当大。与find()的复杂性类似,我更喜欢O(logn)中的解决方案

谢谢


Yoann

std::set
使用
操作符如果您想在查找代码或映射时使用O(logn),那么
std::set
不是正确的容器,因为它只按一个顺序排序。您需要的是一个双映射,其值是指向另一个映射中的条目的指针。这样,每个成员都是其映射中的一个键,可以在O(logn)中找到


如果您可以使用boost,请选中

可能您应该创建几个容器(两个或三个)。 例如:

std::list<mapping> storage; // actual storage
std::multiset<mapping*, compare_by_code_functor> by_code; // sorted by code
std::set<mapping*, compare_by_label_functor> by_label; // sorted by label
std::列表存储;//实际存储
std::multiset by_code;//按代码排序
std::由_标签设置;//按标签排序

std::列表存储;//实际存储
std::multiset by_code;//按代码排序
std::由_标签设置;//按标签排序

正如@PiotrNycz所指出的,
std::set
根本不使用或关心
操作符==
,只有
操作符如果一个类可以合理地按其多个字段排序,它就不应该有关系操作符(除了
操作符==
操作符!=


是,
std::map
std::set
默认使用
std::less
作为比较器(它使用
运算符不幸的是,通过“return(code标签
,而不是检查不相等性。
operator@rubenvb我可能很愚蠢,但是…有什么区别?在我看来,如果字符串相同,比较标签意味着求值。例如
返回代码std::set::find
是O(log(N)),
std::find
是O(N),其中N是元素总数。顺便说一句,operator@stefaanv所以
std::string(“that”)
std::string(“this”)
小?一个包含1和10的
std::set
比一个只包含2的要小?@aschepler:是的,显然,即使对于一个没有多大意义的集合来说。你似乎不同意我写的,但我不确定你的意思。我的观点是,如果您使用Operator,我们将非常感谢您提供这一非常清楚和有用的答复。我从中学到了很多。@YoannPitarch:表达你的感激之情的方法是对答案进行投票。尽管如此,我还是很感激你的好话:)关键是我不能对你的回答投赞成票,因为我是一个新手,没有15个名声。
m2 exists
But it is different according to the definition of the == operator
return code < map.code || (!(map.code < code) && label < map.label);
std::list<mapping> storage; // actual storage
std::multiset<mapping*, compare_by_code_functor> by_code; // sorted by code
std::set<mapping*, compare_by_label_functor> by_label; // sorted by label
std::list<mapping> storage; // actual storage
std::multiset<std::list<mapping>::iterator, compare_by_code_functor> by_code; // sorted by code
std::set<std::list<mapping>::iterator, compare_by_label_functor> by_label; // sorted by label
itTmp = std::find(this->fn[0].begin(), this->fn[0].end(), m2);
struct point2d { int x, y; };
struct less_point2d_by_x {
    typedef bool result_value;
    // the mixed overloads are for use in std::lower_bound and similar
    bool operator()( int lhs, int rhs ) const { return lhs < rhs; }
    bool operator()( int lhs, point2d rhs ) const { return lhs < rhs.x; }
    bool operator()( point2d lhs, int rhs ) const { return lhs.x < rhs; }
    bool operator()( point2d lhs, point2d rhs ) const { return lhs.x < rhs.x; }
};
// same for _y
std::vector<point2d> v = ...;
std::sort(v.begin(), v.end(), less_point2d_by_x()); // sort by x
std::sort(v.begin(), v.end(), less_point2d_by_y()); // sort by y

std::set<point2d, less_point2d_by_x> orderedByX;
std::set<point2d, less_point2d_by_y> orderedByY;
template <template <typename T> class Op=std::less>
struct point2d_by_x {
    typedef bool result_value;
    // the mixed overloads are for use in std::lower_bound and similar
    bool operator()( int lhs, int rhs )         const { return Op<int>()(lhs, rhs); }
    bool operator()( int lhs, point2d rhs )     const { return Op<int>()(lhs, rhs.x); }
    bool operator()( point2d lhs, int rhs )     const { return Op<int>()(lhs.x, rhs); }
    bool operator()( point2d lhs, point2d rhs ) const { return Op<int>()(lhs.x, rhs.x); }
};
// same for _y
std::vector<point2d> v = ...;
std::sort(v.begin(), v.end(), point2d_by_x<std::less>()); // sort ascending by x
std::sort(v.begin(), v.end(), point2d_by_x<>()); // same
std::sort(v.begin(), v.end(), point2d_by_x<std::greater>()); // sort descending by x
// find the position where a `point2d` with `x = 14` would go in the ordering:
std::lower_bound(v.begin(), v.end(), 14, point2d_by_x<std::greater>());

std::set<point2d, point2d_by_x<std::less> > increasingXOrder;
std::set<point2d, point2d_by_y<std::less> > increasingYOrder;