2013-08-06 59 views
1

我正在做一些測試,發現,equal_range和我自己的二進制搜索功能,我有一些麻煩理解爲什麼equal_range需要這麼長時間與查找比較。查找vs等於範圍和性能

我有一個排序的向量,我時間的搜索操作的持續時間。最初的想法是查看find和equal_range之間的性能差異,但我期待的是,隨着數據量的增長,迭代遍歷向量會比二分搜索更糟糕,而這種情況沒有發生。

我的代碼很簡單,但我「懷疑」在這裏有什麼錯,我不知道是什麼。

- 編輯 - 我在VS2012做這些測試 -

 #include "stdafx.h" 
     #include <vector> 
     #include <algorithm> 
     #include <chrono> 
     #include <iostream> 
     #include <list> 

     using namespace std; 

     #define TIMING 

     #ifdef TIMING 
     #define INIT_TIMER auto start = std::chrono::high_resolution_clock::now(); 
     #define START_TIMER start = std::chrono::high_resolution_clock::now(); 
     #define STOP_TIMER(name) std::cout << name << ": " << \ 
      std::chrono::duration_cast<std::chrono::nanoseconds>(\ 
      std::chrono::high_resolution_clock::now()-start \ 
      ).count() << " ns " << std::endl; 
     #else 
     #define INIT_TIMER 
     #define START_TIMER 
     #define STOP_TIMER(name) 
     #endif 

     template<typename T> int mybsearch(const std::vector<T>& vec, unsigned start, unsigned end, const T& key) 
     { 
      // Termination condition: start index greater than end index 
      if(start > end) 
      { 
       return -1; 
      } 

      // Find the middle element of the vector and use that for splitting 
      // the array into two pieces. 
      unsigned middle = start + ((end - start)/2); 

      if(vec[middle] == key) 
      { 
       return middle; 
      } 
      else if(vec[middle] > key) 
      { 
       return mybsearch(vec, start, middle - 1, key); 
      } 

      return mybsearch(vec, middle + 1, end, key); 
     } 

     template<typename Iterator, typename T> Iterator Tbsearch(Iterator& begin, Iterator& end, const T& key) 
     { 
      // Keep halving the search space until we reach the end of the vector 
      Iterator NotFound = end; 

      while(begin < end) 
      { 
       // Find the median value between the iterators 
       Iterator Middle = begin + (std::distance(begin, end)/2); 

       // Re-adjust the iterators based on the median value 
       if(*Middle == key) 
       { 
        return Middle; 
       } 
       else if(*Middle > key) 
       { 
        end = Middle; 
       } 
       else 
       { 
        begin = Middle + 1; 
       } 
      } 

      return NotFound; 
     } 

     int _tmain(int argc, _TCHAR* argv[]) 
     { 
      vector<int> V; 
      typedef vector<int>::iterator it; 
      std::pair<it,it> res; 
      it val; 

      list<int> L; 
      typedef list<int>::iterator itL; 
      std::pair<itL,itL> lpair; 
      itL lval; 

      for(int i=0; i<1000000; i++) 
      { 
       V.push_back(i+1); 
       L.push_back(i+1); 
      } 

      INIT_TIMER 

      cout << "-- find --\n"; 
      for(int k=0;k<10;k++) 
      { 
       int look = pow(k,k); 

       START_TIMER 
       val = std::find(V.begin(),V.end(),look); 
       STOP_TIMER("find took ") 

       if(val!=V.end()) 
        cout << look << " found\n"; 
       else 
        cout << look << " not found\n" ; 
      } 
      cout << "-- homemade bsearch (index) --\n"; 
      for(int k=0;k<10;k++) 
      { 
       int look = pow(k,k); 

       START_TIMER 
       int a = mybsearch(V, 0, V.size()-1, look); 
       STOP_TIMER("find took ") 

       if(a>0) 
        cout << look << " found\n"; 
       else 
        cout << look << " not found\n" ; 
      } 

      cout << "-- homemade bsearch (iterators) --\n"; 
      for(int k=0;k<10;k++) 
      { 
       int look = pow(k,k); 

       START_TIMER 
       it f = Tbsearch(V.begin(), V.end(), look); 
       STOP_TIMER("find took ") 

       if(f!=V.end()) 
        cout << look << " found\n"; 
       else 
        cout << look << " not found\n" ; 
      } 



      cout << "-- equal range --\n"; 
      for(int k=0;k<10;k++) 
      { 
       int look = pow(k,k); 

       START_TIMER 
       res = std::equal_range(V.begin(),V.end(),look); 
       STOP_TIMER("equal_range took ") 

       if(res.first!=res.second) 
        cout << look << " found\n"; 
       else 
        cout << look << " not found\n" ; 
      } 

      return 0; 
     } 

該運行的輸出是

-- find -- 
    find took : 0 ns 
    1 found 
    find took : 0 ns 
    1 found 
    find took : 0 ns 
    4 found 
    find took : 0 ns 
    27 found 
    find took : 0 ns 
    256 found 
    find took : 0 ns 
    3125 found 
    find took : 0 ns 
    46656 found 
    find took : 2000200 ns 
    823543 found 
    find took : 2000200 ns 
    16777216 not found 
    find took : 2000200 ns 
    387420489 not found 
    -- homemade bsearch (index) -- 
    find took : 0 ns 
    1 not found 
    find took : 0 ns 
    1 not found 
    find took : 0 ns 
    4 found 
    find took : 0 ns 
    27 found 
    find took : 0 ns 
    256 found 
    find took : 0 ns 
    3125 found 
    find took : 0 ns 
    46656 found 
    find took : 0 ns 
    823543 found 
    find took : 0 ns 
    16777216 not found 
    find took : 0 ns 
    387420489 not found 
    -- homemade bsearch (iterators) -- 
    find took : 0 ns 
    1 found 
    find took : 0 ns 
    1 found 
    find took : 0 ns 
    4 found 
    find took : 0 ns 
    27 found 
    find took : 0 ns 
    256 found 
    find took : 0 ns 
    3125 found 
    find took : 1000100 ns 
    46656 found 
    find took : 1000100 ns 
    823543 found 
    find took : 0 ns 
    16777216 not found 
    find took : 0 ns 
    387420489 not found 
    -- equal range -- 
    equal_range took : 683068300 ns 
    1 found 
    equal_range took : 681068100 ns 
    1 found 
    equal_range took : 681068100 ns 
    4 found 
    equal_range took : 679067900 ns 
    27 found 
    equal_range took : 679067900 ns 
    256 found 
    equal_range took : 680068000 ns 
    3125 found 
    equal_range took : 683068300 ns 
    46656 found 
    equal_range took : 677067700 ns 
    823543 found 
    equal_range took : 680068000 ns 
    16777216 not found 
    equal_range took : 678067800 ns 
    387420489 not found 

乾杯

+0

「不成熟的優化...無處不在的優化...」 – 2013-08-06 13:51:46

+2

似乎不太可能,equal_range事實上需要超過半秒才能完成一百萬個項目的矢量。運行該程序時是否注意到了控制檯上的延遲?以這種方式的定時功能也容易產生不正確的值。 – dunc123

+0

@ dunc123是的,我知道......但我實際上可以看到它每次花費半秒鐘的時間。 –

回答

0

在調試版本VS2012我

-- equal range -- 
equal_range took : 796079600 ns 
1 found 
equal_range took : 792079200 ns 
1 found 
equal_range took : 785078500 ns 
4 found 
equal_range took : 786078600 ns 
27 found 
equal_range took : 785078500 ns 
256 found 
equal_range took : 784078400 ns 
3125 found 
equal_range took : 785078500 ns 
46656 found 
equal_range took : 786078600 ns 
823543 found 
equal_range took : 784078400 ns 
16777216 not found 
equal_range took : 784078400 ns 
387420489 not found 

而在發佈的版本中,我得到了

-- equal range -- 
equal_range took : 0 ns 
1 found 
equal_range took : 0 ns 
1 found 
equal_range took : 0 ns 
4 found 
equal_range took : 0 ns 
27 found 
equal_range took : 0 ns 
256 found 
equal_range took : 0 ns 
3125 found 
equal_range took : 0 ns 
46656 found 
equal_range took : 0 ns 
823543 found 
equal_range took : 0 ns 
16777216 not found 
equal_range took : 0 ns 
387420489 not found 

迭代器檢查調試版本會減慢很多。