矢量作为两个其他矢量拼凑而成

时间:2016-11-15 05:09:06

标签: c++ performance loops vector iterator

子集矢量

下面是两个不同的解决方案的基准,用于对矢量进行子集化

#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的东西。有更快的解决方案吗?

1 个答案:

答案 0 :(得分: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的长度相同。