我正在实现一种算法,该算法意味着大量检查元素是否在集合/列表中。我当时使用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;
}
您知道为什么要花费这么多时间,更重要的是,如何使其更快?
答案 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]);
}