【发布时间】:2021-11-12 02:07:47
【问题描述】:
我想知道编写 DFS 遍历的最优雅的方法是什么,可以适应解决不同的问题(在 C++ 中)。
我正在考虑将函数指针和void * 传递给我的函数,并让用户传递将在每个节点上使用的回调。
这就是我所拥有的:
traversals.hpp
typedef std::shared_ptr<struct Node> NodePtr;
typedef std::vector<NodePtr> NodeVector;
struct Node {
int id{0};
NodeVector children;
};
bool NodeIsInVector(NodePtr node, NodeVector node_vector);
void DFS(NodePtr node, void (*callback)(NodePtr, void * userdata)=nullptr, void * userdata=nullptr);
traversals.cpp
bool NodeIsInVector(NodePtr node, NodeVector node_vector){
auto result = std::find(node_vector.begin(), node_vector.end(), node);
return result != node_vector.end();
}
void DFS(NodePtr node, void (*callback)(NodePtr, void * userdata), void * userdata){
static NodeVector visited;
if (!NodeIsInVector(node, visited)) {
visited.push_back(node);
if (callback){
callback(node, userdata);
}
}
for (auto&& n : node->children){
if (!NodeIsInVector(n, visited)){
DFS(n, callback, userdata);
}
}
}
驱动代码
这里的回调只计算节点和增量和整数。假设 root 是一个 Node 指针并且定义了一个树。树有7个节点,所以count的值在遍历后预计为7。
int count = 0;
DFS(root, [](NodePtr node, void * count){ ++*(int*)count; }, (void*) &count);
std::cout << "DFS count: there are " << count << " nodes.\n";
但是输出是:
DFS count: there are 0 nodes. 回调被调用(通过输出到标准输出来验证)。问题是 userdata 变量没有得到更新。
我的问题是:
- 这是实现我想要的有效方法吗?有更好的方法吗?
- 我犯了什么错误?
【问题讨论】:
-
void(*)(void*)指针和void*数据对适用于 C 回调,但在 C++ 中我通常更喜欢std::function<void()>。 (或尽可能使用模板参数。)
标签: c++ graph depth-first-search traversal