我对严格的弱排序以及在定义operator<时如何使用它感到困惑。我有几个结构:
struct Plane
{
std::string name;
int xrudder;
int yrudder;
int wingwidgets;
bool hasLegacyEngine;
};
struct Airport
{
bool securityCheck;
unsigned __int64 capacity;
std::vector<Plane> planes;
};
我想创建std::set
个机场。我需要定义运算符&lt;它使用严格的弱排序,但我不确切地知道这意味着什么和/或如何做。
struct cmpless
{
bool operator()(const Airport& left, const Airport& right)
{
//?
}
};
std::set<Airport, cmpless> airportSet;
一个机场“小于”另一个机场是没有意义的。只有机场根据他们的统计数据相等才有意义。
我怎样才能确定我对运算符的定义&lt;会遵循严格的弱序吗?如何在这种情况下开始考虑定义operator<
?
如果可能的话,一个解释的例子会很棒!
答案 0 :(得分:5)
如果一个Airport
在另一个Airport
之前“没有意义”,那么使用std::set<Airport>
也没有意义。此容器利用订单金额元素在O(log(n))
操作中查找对象(其中n
是容器的大小)。如果您只能通过标识识别对象,那么您可以实现的最佳复杂性是O(n)
。您可以使用std::find()
或std::find_if()
和其中一个序列容器的组合,例如std::vector<Airport>
或std::deque<Airport>
。
由于您不需要根据operator<()
定义订单,因此将Airport
置于某个顺序以便将其定位在{{1}中可能是合理的。这是通过使用与std::set<Airport>
不同的比较函数对象来完成的。但是,您当前在std::less<Airport>
对象中的属性看起来并不像合适的键。事实上,它们看起来都像是可变的,也就是说,你可能不会想要Airport
,因为你无法修改std::set<Airport>
中的元素(至少,你不应该;是的,我意识到你可以用std::set<T>
玩弄技巧,但这必然会破坏元素的顺序。)
基于此,我建议使用mutable
:std::map<std:string, Airport>
用于识别机场,例如,使用std::string
等机场代码来识别John F.纽约肯尼迪机场或伦敦希思罗机场"JFK"
。方便的是,字符串上已经定义了严格的弱顺序。
也就是说,要在一组对象"LHR"
上定义strict weak order,您需要一个二元关系O
,以便以下条件适用于元素r(x, y)
,来自x
的{{1}}和y
:
z
O
隐含r(x, x) == false
r(x, y) == true
和r(y, x) == false
暗示r(x, y) == true
r(y, z) == true
和r(x, z) == true
以及r(x, y) == false
和r(y, x) == false
隐含r(y, z) == false
和r(z, y) == false
前三个应该足够简单。最后一个有点奇怪,但实际上也不是那么难:基本思想是关系不完全对元素进行排序,而是将它们分组为等价的类。如果您认为关系r(x, z) == false
“小于”它只是表示如果r(z, x) == false
小于r
且x
小于y
,然后y
和x
是等效的。无与伦比的元素恰好相同。
标准容器使用严格的弱顺序,但例如x
和y
只保留一个版本的等效键。很好,这是足够的,但通常使用一个严格弱顺序的总顺序更简单,其中每对元素std::set<T>
和std::map<K, V>
x
或{{ 1}}(但是,由于不对称而不是两者)。
答案 1 :(得分:1)
在musingstudio blog上找到了一个很好的解决方案,并认为我在这里为下一个需要的人分享它(即使Dietmar可能是正确的,地图不合适):</ p>
bool operator <(const T& rhs) const
{
if (a < rhs.a)
return true;
else if (rhs.a < a)
return false;
if (b < rhs.b)
return true;
else if (rhs.b < b)
return false;
// repeat for all child elements c, d, e etc
return false;
}
答案 2 :(得分:0)
如果每个成员都定义了<
,你可以做类似于lexiographical命令的事情:
struct cmpless
{
bool operator()(const Airport& left, const Airport& right)
{
return
left.securityCheck < right.securityCheck
|| ((left.securityCheck == right.securityCheck
&& left.capacity < right.capacity)
|| (left.capacity == right.capacity
&& left.planes < right.planes));
}
};