std set insert和union有效的方法

时间:2014-11-13 17:59:23

标签: c++ algorithm set stl-algorithm stdset

我正在努力解决一个问题,我正在尝试使用联合,并尝试使用非常简单的基准测试代码来查看效率。

代码非常简单(插入)数百万个元素到集合中。 为了简单起见,请让set_union远离讨论。

测试代码:

int main() {
  // Setting up
    int num = 40000000;
  auto it = v.begin();
  std::vector<int> a;
  a.reserve(num);
  for (int i =0;i < num ; ++i) {
    a.push_back(i);
  }

  // Method 1
  { 
    std::set<int> v;    
    for (int i= 0 ; i< num ; ++i) {
       v.insert(a[i]);
    }
  }

  // Method 2
  { 
    std::set<int> v;
    auto it = v.begin();
    for (int i= 0 ; i< num ; ++i) {
       it = v.insert(it,a[i]);
    }
  }  

  // Method 3
  { 
    std::set<int> v;
    auto it = v.begin();
    for (int i= 0 ; i< num ; ++i) {
       it = std::next(v.insert(it,a[i]));
    }
  }

  // Method 4
  { 
    std::set<int> v;
    auto it = v.begin();
    for (int i= 0 ; i< num ; ++i) {
       it = v.insert(it,i); ++it;
    }
  }    

  // Method 5 : idiomatic
  {
    std::set<int> v;
    std::copy(a.begin(), a.end(), std::inserter(v,v.end()));
  }
 return 0;
}

方法1:最慢(如预期):约38秒 方法2:最快(如预期):~8秒 方法3:约20秒 方法4:约20秒 方法5:~20秒

结果有意义方法3和4是相同的并且在挖掘mehtod 5时我发现std :: inserter创建了一个输出迭代器,它在赋值时与方法3完全相同(或转换为相同) 4。

这是故意的吗?为什么算法不能以最有效的插入方式编写?方法2给出了精确的准确提示,而3,4,5将迭代器增加到set.end()(在这种情况下,当我插入一个排序范围时,std :: next(insert(pos,new_max_element))== set :: end())并始终将其作为插入提示。

如果我使用std :: inserter将迭代器传递给这样的有序容器,这使得使用stl算法效率低下。 在旁注: 我不明白如果对另一组的插入操作是对数的,set_union如何在线性时间内工作。对于exmaple set_union(set_1.begin(),set_1.end(),set_2.begin(),set_2.end(),std :: inserter(output_set,output_set.end())。排序向量很好但是设置了吗? 任何人都可以对复杂性分析进行一些链接或推荐吗?

如果有人可以解释或提供复杂性分析的一些推荐,这将证明插入具有正确提示的集合(例如,下一个数字总是小于或大于插入的当前数据)会给您的算法带来好处amoritzed constant complexity而不是logn。

0 个答案:

没有答案