2016-11-15 50 views
0

子集的載體的矢量作爲其他兩個矢量

下面的拼湊是兩個不同的解決方案基準到子集的載體

#include <vector> 
#include <iostream> 
#include <iomanip> 
#include <sys/time.h> 

using namespace std; 

    int main() 
    { 
      struct timeval timeStart, 
        timeEnd; 

      // Build the vector 'whole' to subset 
      vector<int> whole; 
      for (int i = 0 ; i < 10000000 ; i++) 
         { 
       whole.push_back(i); 
      } 

      // Solution 1 - Use a for loops 
      gettimeofday(&timeStart, NULL); 
      vector<int> subset1; 
      subset1.reserve(9123000 - 1200); 
      for (int i = 1200 ; i < 9123000 ; i++) 
      { 
       subset1.push_back(i); 
      } 
      gettimeofday(&timeEnd, NULL); 

      cout << "Solution 1 took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl; 

      // Solution 2 - Use iterators and constructor 
      gettimeofday(&timeStart, NULL); 
      vector<int>::iterator first = whole.begin() + 1200; 
      vector<int>::iterator last = whole.begin() + 9123000; 
      vector<int> subset2(first, last); 
      gettimeofday(&timeEnd, NULL); 

      cout << "Solution 2 took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl; 
} 

在我的舊的筆記本電腦,它輸出

Solution 1 took 243564 us 
Solution 2 took 164220 us 

顯然,解決方案2速度更快。

使兩個矢量

的拼湊我想創建矢量作爲相同大小的兩個不同載體的拼湊。該矢量從一個開始,然後來回採用另一個的值。我想我不完全理解如何通過使用迭代器指向另一個向量中的元素來將值複製到向量。我能想到的唯一實現需要使用類似於上面的解決方案1。喜歡的東西...

#include <vector> 
#include <iostream> 
#include <cmath> 
#include <iomanip> 
#include <sys/time.h> 
#include <limits.h> 

using namespace std; 

int main() 
{ 

    // input 
    vector<int> breakpoints = {2, 5, 7, INT_MAX}; 
    vector<int> v1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    vector<int> v2 = { 10, 20, 30, 40, 50, 60, 70, 80, 90 }; 

    // Create output 
    vector<int> ExpectedOutput; 
    ExpectedOutput.reserve(v1.size()); 
    int origin = 0; 
    int breakpoints_index = 0; 
    for (int i = 0 ; i < v1.size() ; i++) 
    { 
    if (origin) 
    { 
     ExpectedOutput.push_back(v1[i]); 
    } else 
    { 
     ExpectedOutput.push_back(v2[i]); 
    } 
    if (breakpoints[breakpoints_index] == i) 
    { 
     origin = !origin; 
     breakpoints_index++; 
    } 
    } 


    // print output 
    cout << "output: "; 
    for (int i = 0 ; i < ExpectedOutput.size() ; i++) 
    { 
    cout << ExpectedOutput[i] << " "; 
    } 
    cout << endl; 

    return 0; 
} 

其輸出

output: 10 20 30 4 5 6 70 80 9 

感覺就像必須有一個更好的解決方案,如從上面的東西類似於解決方案2。有更快的解決方案嗎?

+0

我懷疑解決方案2的速度要快得多,因爲編譯器設法將它優化爲單個memcpy調用(或機器代碼中的等價物)。對於交叉兩個向量的內容的任務來說,巧妙程度不會有同樣的效果。 –

+0

哦......所以我猜想,隨着兩個源矢量的「塊」變得足夠大,在單獨的「memcpy」(我不知道該函數在讀取您的評論之前)調用每個而不是複製每個元素(在本例中分別爲「int」),對嗎? –

回答

1

重複push_back()意味着每次在循環周圍進行檢查以確保capacity()足夠大(如果沒有,則必須保留更多空間)。當您複製整個範圍時,只需要完成一個capacity()檢查。

通過複製塊,您仍然可以通過交叉存儲更智能一些。這裏是非常基本的想法:

int from = 0; 
for(int b : breakpoints) 
{ 
    std::swap(v1, v2); 
    int to = 1 + std::min(b, static_cast<int>(v1.size()) - 1); 
    ExpectedOutput.insert(ExpectedOutput.end(), v1.begin() + from, v1.begin() + to); 
    from = to; 
} 

爲了簡潔起見,這段代碼實際上交換v1v2等始終v1工作。我在插入之前做了的交換,以模擬代碼中的邏輯(它首先在v2上執行)。如果需要,您可以以非修改的方式完成此操作。

當然,您可以在此代碼中看到更多內容。只有在斷點比斷點少得多的情況下才有意義。請注意,它也假定v1v2長度相同。