检查元素是否在C ++集中真的很慢

时间:2019-01-08 10:54:58

标签: c++ performance set

我正在实现一种算法,该算法意味着大量检查元素是否在集合/列表中。我当时使用std::vector容器,但是随着向量的增长,时间呈指数增长。

我决定我将尝试使用std::set容器,以便不必浏览整个容器来知道它是否包含某个元素。 我实现了以下功能,用于检查元素是否为给定集合的一部分:

bool in_set(set<Node> node_set){
  return node_set.find(*this) != node_set.end();
}

但是,对于很小的一组(1-3个元素),该功能大约需要2秒钟,这使我的整个算法无法使用。

我正在使用的自定义类如下:

class Node{
    public:
      int d;
      int h_score;
      int coordinates [3];
      Node* parent_address;
};

我实现的比较运算符如下:

bool operator<(Node other) const{
  return concatenate(concatenate(this->coordinates[0], this->coordinates[1]), this->coordinates[2]) < 
  concatenate(concatenate(other.coordinates[0], other.coordinates[1]), other.coordinates[2]);
}

编辑:连接函数似乎在执行时并不需要很多时间,它看起来像这样:

int concatenate(int i, int j) {
    int result = 0;
    for (int x = i; x <= j; x++) {
       result = result * 10 + x;
    }
    return result;
}

您知道为什么要花费这么多时间,更重要的是,如何使其更快?

3 个答案:

答案 0 :(得分:2)

首先,您可以尝试将Set传递为const&,而不是在operator <中也传递为const&。

bool in_set(const set<Node>& node_set){
  return node_set.find(*this) != node_set.end();
}

还有

bool operator<(const Node& other) const

它将使用ref代替集合和Node对象的副本。

答案 1 :(得分:1)

  

你知道为什么要花这么长时间吗

concatenate(1, 100000000)在我的树莓派上花了1.3秒,这种方式太慢了,实际上没用

还请注意,由于可能发生的 concatenate 溢出可以为不同的节点提供相同的结果,因此对于 operator << / em>

不兼容
  

如何使其更快?

除了这些串联调用之外,您还必须找到其他东西来实现您的 operator << / em>

您需要什么?集合中的顺序重要吗,或者可以用其他任何顺序替换?

创建唯一的标识符来比较两个节点并直接比较它们不是强制性的,例如:

bool operator<(const Node & other) const{
  if (coordinates[0] < other.coordinates[0]) 
    return true;
  if (coordinates[0] >= other.coordinates[0]) 
    return false;

  if (coordinates[1] < other.coordinates[1])
    return true;
  if (coordinates[1] >= other.coordinates[1])
    return false;

  return (coordinates[2] < other.coordinates[2]);
}

要了解 operator << / em>的工作原理,可以考虑 node.coordinates 支持的数字是 int 的3倍,因此我比较高位,如果等于中位,则等于低位用于 set

答案 2 :(得分:0)

您的operator<对节点进行复制。也无需创建字符串进行比较,内置的tuple类可以做到这一点:

怎么样:

bool operator<(const Node& other) const {
    return std::make_tuple(coordinates[0], coordinates[1], coordinates[2]) < 
           std::make_tuple(other.coordinates[0], other.coordinates[1], other.coordinates[2]);
}