[英]strict weak ordering confusion
我對嚴格弱排序以及在定義 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
機場。 我需要定義 operator< ,它使用嚴格的弱排序,但我不知道這到底是什么意思和/或如何去做。
struct cmpless
{
bool operator()(const Airport& left, const Airport& right)
{
//?
}
};
std::set<Airport, cmpless> airportSet;
一個機場“小於”另一個機場是沒有意義的。 僅當機場根據其統計數據相等時才有意義。
我如何確定我對 operator< 的定義將遵循嚴格的弱排序? 在這種情況下,我如何開始考慮定義operator<
?
如果可能的話,一個帶有解釋的例子會很棒!
如果一個Airport
在另一個Airport
之前“沒有意義”,那么使用std::set<Airport>
也沒有意義。 此容器利用訂單金額元素在O(log(n))
操作(其中n
是容器的大小O(log(n))
定位對象。 如果您只能通過身份識別對象,那么您可以實現的最佳復雜度是O(n)
。 您可以使用std::find()
或std::find_if()
與序列容器之一的組合,例如std::vector<Airport>
或std::deque<Airport>
。
由於您不需要根據operator<()
定義順序,因此為了將它們定位在std::set<Airport>
,將Airport
放入某個順序可能是合理的,這是由使用與std::less<Airport>
不同的比較函數對象。 但是,您當前在Airport
對象中擁有的屬性看起來並不像合適的鍵。 事實上,它們看起來好像都是可變的,也就是說,您可能無論如何都不想要std::set<Airport>
,因為您無法修改std::set<T>
的元素(好吧,至少,您不應該;是的,我意識到您可以使用mutable
來玩弄技巧,但這勢必會破壞元素的順序)。
基於此,我建議使用std::map<std:string, Airport>
: std::string
用於標識機場,例如,使用像"JFK"
這樣的機場代碼來表示 John F.紐約肯尼迪機場或倫敦希思羅機場的"LHR"
。 方便的是,已經在字符串上定義了嚴格的弱順序。
也就是說,要在一組對象O
上定義嚴格的弱順序,您需要一個二元關系r(x, y)
使得以下條件對來自O
元素x
、 y
和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));
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.