簡體   English   中英

與三值比較函數相比,僅使用小於運算符進行排序

[英]Sorting only using the less-than operator compared to a trivalue compare function

在C ++ / STL中,僅使用less-than運算符進行排序。 盡管我不知道排序算法是如何實際實現的,但我認為其他操作是隱含的:

a > b *equals* b < a == true
a == b *equals* !(a < b) && !(b < a)

與使用trivalue * compare函數(例如Java)相比,這對性能有好處,或者為什么要做出這樣的設計決策呢?

我的假設是,任何trivalue compareto函數仍然必須實現這些比較,從而產生相同的性能。

**通過trivalue比較函數,我的意思是比較函數,它返回-1,0和1小於,等於和大於*

更新:似乎太空船<=>運營商正在使用C ++ 20,所以顯然委員會認為僅使用operator<缺點。

從某種意義上說,另外兩個是隱式的,但更准確的是說比較排序實際上並不需要三值比較器,並且C ++的排序是以不使用一個的方式實現的,以便最小化比較器所需的行為。

std :: sort定義並專門使用這樣的東西是錯誤的:

template <typename T, typename Cmp>
int get_tri_value(const T &a, const T &b, Cmp lessthan) {
    if (lessthan(a,b)) return -1;
    if (lessthan(b,a)) return 1;
    return 0;
}

......因為你最終在呼叫數量方面的低效算法lessthan 如果你的算法沒有對1返回和0返回之間的差異做任何有用的事情,那么你就浪費了一個比較。

C ++指的是“嚴格的弱排序”。 如果<是嚴格的弱排序,並且!(a < b) && !(b < a) ,則不一定遵循a == b 它們在排序中只是“在同一個地方”,並且!(a < b) && !(b < a)是等價關系。 因此,所要求的比較sort順序等價 ,它並沒有提供一個總訂單。

唯一的區別就是你說的時候!(a < b) 對於嚴格的總訂單,您將推導出b <= a ,讀取“小於或等於”。 對於嚴格的弱序,您不能將b <= a定義為b < a || b == a b < a || b == a並且這是真的。 C ++對此很迂腐,因為它允許運算符重載它幾乎必須如此,因為人們重載運算符需要術語,以便告訴用戶他們的代碼在運算符如何關聯方面可以期待什么。 Java確實討論了比較器和hashCode與equals一致,這就是你所需要的。 C ++必須處理<,>,==,<=,> =,賦值的后置條件,等等。

C ++在API中采用了相當純粹的數學方法,因此所有內容都是根據單個二元關系定義的。 Java在某些方面更友好,並且更喜歡三向比較,其中基本單元的定義(比較)稍微復雜一些,但是由它引出的邏輯更簡單。 這也意味着排序算法在每次比較時獲得更多信息,這有時是有用的。 例如,請參閱“荷蘭旗”快速排序優化,這在數據中存在大量“在同一位置”重復時是一個好處。

在這種情況下,三值比較器是速度增益。 但C ++使用比較器的一致定義進行排序,也使用setmaplower_bound等,這幾乎不受三值比較器的影響(可能保存一個比較,也許不是)。 我猜他們決定不為了特定或有限的潛在效率增益而使他們漂亮的通用界面復雜化。

我在C ++中的猜測只是為了減少代碼重復:一旦你在類/類型上定義了一個比較操作,你不僅可以通過簡單地寫一個<b來比較這些對象,而且還可以對這些對象進行排序。這樣的對象。

至於排序,我們只需要少於運營商,為什么要引入額外的東西? :)

如果你指的是std :: sort(),它只使用less()運算符,因為它不需要保留等效元素的相對排序,所以它只需要less()運算符和隱式big()運算符。

雖然std :: stable_sort會保留它,但速度較慢。 它需要less()運算符和雙向迭代器來交換equal()運算符來構造“trivalue”比較函數

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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