我对严格的弱排序以及如何在定义运算符时使用它感到困惑<。我有几个结构:
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
。我需要定义运算符
struct cmpless
{
bool operator()(const Airport& left, const Airport& right)
{
//?
}
};
std::set<Airport, cmpless> airportSet;
一个机场"小于"另一个机场是没有意义的。只有当机场根据其统计数据相等时才有意义。
我如何确定我的运算符<定义将遵循严格的弱排序?在这种情况下,我如何开始考虑定义operator<
?>
如果可能的话,带有解释的示例会很棒!
如果一个Airport
先于另一个Airport
"没有意义",那么使用std::set<Airport>
也没有意义。此容器利用订单金额元素在O(log(n))
操作中定位对象(其中n
是容器的大小)。如果只能通过标识来识别对象,则可以实现的最佳复杂性是O(n)
。您可以使用std::find()
或std::find_if()
和序列容器之一的组合,例如,std::vector<Airport>
或std::deque<Airport>
。
由于您不需要根据operator<()
定义顺序,因此只需将Airport
按某种顺序排列,以便将它们定位在std::set<Airport>
中可能是合理的,这是通过使用与std::less<Airport>
不同的比较函数对象来完成的。但是,您当前在Airport
对象中的属性看起来并不像合适的键。事实上,它们看起来都是可变的,也就是说,你可能无论如何都不需要std::set<Airport>
,因为你不能修改std::set<T>
中的元素(好吧,至少,你不应该;是的,我意识到你可以和mutable
玩弄,但这势必会破坏元素的顺序)。
基于此,我建议使用std::map<std:string, Airport>
:std::string
用于识别机场,例如,使用机场代码,如纽约约翰肯尼迪机场的"JFK"
或伦敦希思罗机场的"LHR"
。方便的是,在字符串上已经定义了严格的弱顺序。
也就是说,要在一组对象O
上定义一个严格的弱序,你需要一个二元关系r(x, y)
使得以下条件对元素x
、y
和O
z
成立:
- 反身:
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
和y
r(x, y) == true
或r(y, x) == true
(但是,由于不对称性,不是两者兼而有之)。
在musingstudio博客上找到了一个不错的解决方案,并认为我在这里分享给下一个需要的解决方案(即使Dietmar可能是对的,地图不合适):
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;
}
如果每个成员都定义了<
,则可以执行类似于字典顺序的操作:
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));
}
};