C ++:使用更大的比较器会意外地提高性能

时间:2019-03-07 07:28:32

标签: c++ operator-keyword

我正在将我的算法问题解决方案提交给在线评分系统,最初,解决方案超出了时间限制,大约需要4 s。

我完全确定复杂性是正确的,所以我开始优化代码的一部分,并没有发生什么大的事情,直到我发现确实很奇怪的东西。

我正在使用成对的优先级队列,因此选择实现自己的比较器

struct Comparator{  
  bool operator()(pair<int, int> node1, pair<int, int> node2){  
      return node1.second < node2.second;  
  }  
}; 

当我将其更改为greater库的<algorithm>比较器时,性能得到了显着提高。解决方案通过了,只花了约300毫秒。

其他信息:我正在使用优先级队列来实现Dijkstra的“调整”版本。队列声明为:priority_queue<pair<int, int>, vector<pair<int, int>>, Comparator> q;,我将其更改为: priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;

我真的很好奇为什么会这样。对我来说,比较器应该做什么很简单,我想不出任何更有效的方法。

任何帮助将不胜感激:)

1 个答案:

答案 0 :(得分:3)

有几件事会导致性能差异:

struct Comparator{  
  bool operator()(pair<int, int> node1, pair<int, int> node2){  
      return node1.second < node2.second;  
  }  
}; 

vs。 std::greater

  1. 自定义比较器按值获取对象,std::greater按引用获取对象。我怀疑这样做的效果是否会超过10%。
  2. std::greater比较node2.first < node1.first是否为node2.first != node1.first,否则为node2.second < node1.second。比较完全不同于Comparator的{​​{1}}。

    由于比较结果不同,因此您的代码将经历完全不同的路径。经历不同的路径会对O的复杂性和性能产生深远的影响。这很可能是造成差异的真正原因。

对于node1.second < node2.second的参考,请查看std::pair::operator<在做什么:

  

如果std::greater,则返回lhs.first<rhs.first。否则,如果true,则返回rhs.first<lhs.first。否则,如果false,则返回lhs.second<rhs.second。否则,返回true