簡體   English   中英

為什么std :: binary_search的參數是前向迭代器?

[英]Why arguments of std::binary_search are forward iterators?

在閱讀http://en.cppreference.com/w/cpp/algorithm/binary_search時,我注意到它將迭代器作為參數。 現在我很困惑,因為我認為它寧願是一個隨機訪問迭代器,所以二進制搜索實際上是二進制的。

為了滿足我的好奇心,我寫了一個小程序:

#include <iostream>
#include <vector>
#include <forward_list>
#include <list>
#include <deque>
#include <algorithm>
#include <chrono>
#include <random>

int main()
{
    std::uniform_int_distribution<int> uintdistr(-4000000, 4000000);
    std::mt19937 twister(std::chrono::high_resolution_clock::to_time_t(std::chrono::high_resolution_clock::now()));
    size_t arr[] = { 200000, 400000, 800000, 1600000, 3200000, 6400000, 12800000 };
    for(auto size : arr)
    {
        std::list<int> my_list;
        for(size_t i = 0; i < size; i++)
            my_list.push_front(uintdistr(twister));
        std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
        my_list.sort(); //fixed
        start = std::chrono::high_resolution_clock::now();

        std::binary_search(my_list.begin(), my_list.end(), 1252525);

        end = std::chrono::high_resolution_clock::now();
        long long unsigned elapsed_time = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
        std::cout << "Test finished in " << elapsed_time << "\n";
    }
}

用gcc 4.7.0編譯並運行

g++ -std=c++11 test.cpp

在我的機器上提供以下結果:

Test finished in 0
Test finished in 15625
Test finished in 15625
Test finished in 46875
Test finished in 93750
Test finished in 171875
Test finished in 312500

所以看起來它實際上並沒有在轉發列表上進行二進制搜索。 現在我的問題是:

為什么這么混亂的名字?

為什么這樣的代碼允許?

為什么參考文獻說它是“第一個和最后一個之間距離的對數”?

標准有什么說法呢?

編輯:現在代碼在搜索之前對列表進行排序 - 愚蠢的錯誤,現在的結果是:

Test finished in 46875
Test finished in 109375
Test finished in 265625
Test finished in 546875
Test finished in 1156250
Test finished in 2625000
Test finished in 6375000

當然還不是對數的;)

原始SGI STL實現的文檔(標准源自該文檔) 指出

比較次數是對數的:最多log(最后 - 第一個)+ 2.如果ForwardIterator是隨機訪問迭代器,那么通過該范圍的步數也是對數的; 否則,步數與last-first成正比。

也就是說, 比較的數量總是對數的,而受缺乏隨機可訪問性影響的進步數量可以是線性的。 在實踐中,可能使用stl::advance ,如果迭代器是隨機訪問,則復雜性是常量,否則是線性的。

如果比較非常昂貴,那么具有線性迭代器數量增量的二分搜索,但具有對數的比較是有意義的。 例如,如果您有一個復雜對象的已排序鏈接列表,需要磁盤或網絡訪問才能進行比較,那么使用二進制搜索比使用線性搜索要好得多。

網站可能會說的相反(例如“ distance(first, last)對數distance(first, last) ”),標准實際上只談到比較 (例如25.4.3.1, lower_bound ):

復雜性:最多log2(last − first) + O(1)比較

迭代器的遞增包括在復雜性中! 請注意,標准庫要求所有迭代器增量都具有分攤的常量復雜度,因此增加迭代器會產生訂單O(N)的成本(但可能這是一個非常小的主導因素)。 特別是(25.4.3):

對於非隨機訪問迭代器[算法]執行線性步數。

該標准指定排序的搜索算法( std::lower_bound()std::upper_bound()std::binary_search() )在前向和二進制迭代器的線性時間內工作。 對於隨機訪問,時間是對數的。

但是請注意, comparisons次數限制為對數。

暫無
暫無

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

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