簡體   English   中英

嚴格弱序混淆

[英]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元素xyz

  • 非自反: r(x, x) == false
  • 不對稱: r(x, y) == true意味着r(y, x) == false
  • 傳遞性: r(x, y) == truer(y, z) == true意味着r(x, z) == true
  • 不可比性: r(x, y) == falser(y, x) == falser(y, z) == falser(z, y) == false意味着r(x, z) == falser(z, x) == false

前三個應該足夠簡單。 最后一個起初有點奇怪,但實際上也沒有那么難:基本思想是關系並不完全對元素進行排序,而是將它們分組到等效的類中。 如果你認為關系r是“小於”,它只是說如果x不小於y也不y小於x ,那么xy是等價的。 無與倫比的元素只是等價的。

標准容器以嚴格的弱順序工作,但例如std::set<T>std::map<K, V>僅保留等效鍵的一個版本。 很好,這已經足夠了,但只使用全序通常更簡單,這是一個嚴格的弱序,其中對於每對元素xy要么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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM