我有一个结构node
和一个类graph
他们看起来像这样:
struct node {
node(const std::string &s) : id(std::hash<std::string>()(s)) { }
node(node &&) = default;
node(const node &) = default;
friend bool operator<(node lhs, node rhs){
return lhs.id < rhs.id;
}
mutable bool visited{false};
const std::size_t id;
mutable std::set<node> neighbors;
mutable std::set<node> back_edges;
};
class graph {
private:
std::set<node> node_set;
public:
size_t add_edge(node from, node to){
//auto start = std::chrono::system_clock::now();
auto iter_from = node_set.insert(from).first;
auto iter_to = node_set.insert(to).first;
iter_from->neighbors.insert(*iter_to);
iter_to->back_edges.insert(*iter_from);
//auto duration = std::chrono::duration_cast<std::chrono::milliseconds>
// (std::chrono::system_clock::now() - start);
//return duration.count();
return -1;
}
std::size_t size(){
return node_set.size();
}
};
现在我想通过生成随机图来测试add_edge
方法。为此我有一个函数,它生成长度为SIZE
的随机字母串:
constexpr size_t SIZE{2};
graph g1;
for (int i = 0; i < 100000; i++){
g1.add_edge(random_string(SIZE), random_string(SIZE));
如果我选择SIZE
不是太小而不是超过5,那么一切正常,但如果我尝试选择SIZE
小到2或甚至1,我会获得巨大的内存占用并且测试需要永远。由于图表应该更小,SIZE
更小(SIZE = 1
- > 26 ^ 2),我真的不明白为什么会发生这种情况。
编辑:对于较小的SIZE
,add_edge
在循环中的每次迭代变得越来越慢。
编辑:这是生成我的随机字符串的函数:
std::string random_string(size_t length) {
static bool initialized{false};
if (!initialized) {
std::srand(std::time(0));
initialized = true;
}
auto randchar = []() -> char {
static const char charset[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const size_t max_index = (sizeof(charset) - 1);
return charset[std::rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
答案 0 :(得分:2)
您目前正在neighbors
和back_edges
存储节点的副本。这可能非常昂贵,因为node
和neighbors
中的每个back_edges
都可以包含自己的neighbors
和back_edges
。您可能希望存储指向节点的指针。
例如,您可以使用:
std::set<node *, Comparator> neighbors;
std::set<node *, Comparator> back_edges;
而不是:
std::set<node> neighbors;
std::set<node> back_edges;
Comparator
的位置:
struct Comparator {
bool operator () (const node * a, const node * b) const {
return !a || b ? *a < *b : false;
}
};
更进一步,您可以更新graph
类以包含:
std::set<std::shared_ptr<node>, Comparator> node_set;
而不是:
std::set<node> node_set;
Comparator
的位置:
struct Comparator {
bool operator () (
const std::shared_ptr<const node> & a,
const std::shared_ptr<const node> & b
) const {
return !a || b ? *a < *b : false;
}
};
然后node
可以更新为包含:
std::set<std::shared_ptr<node>, Comparator> neighbors;
std::set<std::shared_ptr<node>, Comparator> back_edges;
另一种选择是使用邻接矩阵代表图形。