簡體   English   中英

為什么要使用std :: less作為默認函子來比較std :: map和std :: set中的鍵?

[英]Why use std::less as the default functor to compare keys in std::map and std::set?

我想知道為什么std::mapstd::set使用std::less作為默認函子來比較鍵。 為什么不使用與strcmp類似的函子? 就像是:

  template <typename T> struct compare
  {
     // Return less than 0 if lhs < rhs
     // Return 0 if lhs == rhs
     // Return greater than 0 if lhs > rhs
     int operator()(T const& lhs, T const& rhs)
     {
        return (lhs-rhs);
     }
  }

假設map有兩個對象,分別為key1key2 現在,我們要插入另一個具有鍵key3對象。

使用std::lessinsert功能需要首先使用key1key3調用std::less::operator() 假設std::less::operator()(key1, key3)返回false。 它必須在切換鍵std::less::operator()(key3, key1) std::less::operator()再次調用std::less::operator() ,以確定key1等於key3還是key3大於key1 有兩次調用std::less::operator()來確定第一個調用是否返回false。

如果std::map::insert使用compare ,那么只需一次調用就可以提供足夠的信息來做出正確的決定。

根據映射中鍵的類型, std::less::operator()(key1, key2)可能會很昂貴。

除非我缺少一些非常基本的知識,否則std::mapstd::set是否應該使用諸如compare之類的東西而不是std::less類的默認函子來比較鍵?

我決定向Alexander Stepanov(STL的設計師)詢問有關此問題的信息。 我被允許引用他如下:

最初,我提出了三向比較。 標准委員會要求我改為使用標准比較運算符。 我做了我被告知的事情。 二十多年來,我一直主張將三路組件添加到標准中。

但是請注意,也許直覺上來說2路並不是很大的開銷。 您不必進行兩次比較。 在下降過程中,每個節點只是一個比較(無相等檢查)。 代價是無法提前返回(當密鑰位於非葉子中時),而最終無法進行一次額外的比較(交換用於檢查相等性的參數)。 如果我沒記錯的話

1 + 1/2*1 + 1/4*2 + 1/8*3 + ...
= 1 + 1/2+1/4+1/8+... + 1/4+1/8+... + ...
-> 3  (depth -> infty)

在包含查詢元素的平衡樹上平均進行額外比較。

另一方面,三向比較沒有可怕的開銷:無分支三向整數比較 現在,是否有一個額外的分支來檢查每個節點的0(相等)比較結果是否比在末尾進行約3個額外的比較要少開銷。這是另一個問題。 可能無關緊要。 但是我認為比較本身應該是3值的,以便可以更改是否使用所有3個結果的決定。

更新:請參閱下面的評論,以了解為什么我認為三向比較在樹中更好,但不一定在平面數組中。

基於樹的容器僅需要嚴格的弱總定貨。

參見https://www.sgi.com/tech/stl/StrictWeakOrdering.html

  1. 寫訪問

    映射和集合的插入點完全由單個二進制搜索(例如lower_boundupper_bound 二進制搜索的運行時復雜度為O(log n)

  2. 讀取權限

    這同樣適用於搜索:搜索是遠遠大於線性平等掃描更高效,正是因為不是最需要的元素進行比較。 訣竅是容器是有序的。


結果是equality信息不必存在。 只是,這些項目可以具有相等的順序

實際上,這僅意味着對元素類型的約束更少,實現需求的工作量減少以及在常見用法場景中的最佳性能。 總是會有權衡的。 (例如,對於大型集合,散列表( 無序集和映射)通常會更高效。請注意,這些equatable 確實需要equatable元素,並且它們采用散列方案進行快速查找)

暫無
暫無

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

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