2016-07-20 40 views
2

std::equal_rangecppreference.com文檔顯示了一個可能的實現:可能實現的std ::的equal_range

template<class ForwardIt, class T> 
std::pair<ForwardIt,ForwardIt> 
    equal_range(ForwardIt first, ForwardIt last, 
       const T& value) 
{ 
    return std::make_pair(std::lower_bound(first, last, value), 
          std::upper_bound(first, last, value)); 
} 

但這看起來更優化的同時仍然很簡單:

template<class ForwardIt, class T> 
std::pair<ForwardIt,ForwardIt> 
    equal_range(ForwardIt first, ForwardIt last, 
       const T& value) 
{ 
    first = std::lower_bound(first, last, value); 
    return std::make_pair(first, 
          std::upper_bound(first, last, value)); 
} 

因爲該解決方案是很明顯的,有什麼理由不使用?

+0

也許是因爲它不那麼直截了當? – user975989

回答

7

上cppreference給出的實現是可能的實施,不一定是最優化的實施。我認爲這是爲了清楚起見,以便讀者能夠更好地理解該算法在內部執行的操作,而不是作爲所有可能的最快實現的指導。

只要您優化實現,您可能會考慮使用一些邏輯來檢查範圍是否較小,如果是,則使用線性搜索而不是二分查找。

查看實際實施以瞭解其結構可能會有幫助。看一看,比如the libstdc++ implementation,它比cppreference中給出的更清晰但效率更低的版本更加難讀。該版本 - 截至撰寫本文時爲止 - 使用完全不同的方法:

  1. 使用初始二進制搜索來搜索元素的任何副本。
  2. 在剩餘窗口中使用二級二分查找來查找該範圍內元素的第一個和最後一個副本。

這種方法可能會比您提出的要快,因爲可以共享兩個二進制搜索中的大量工作。

+1

有時在cppreference上給出的實現是不正確的實現,因爲它不適用於一些需要更多代碼或SFINAE技巧的角落案例。 –

+0

不太明白二次二進制搜索爲什麼需要搜索第一個副本。 – Slava

+0

@Slava第一次二元搜索會縮小搜索範圍的上限和下限,直到找到副本。您的實施只能通過移動下限來縮小範圍。 – SirGuy