背景
我已经定义了树上的格式化操作,当它们被使用前/中/后顺序操作符时,效果非常好,具有以下结构和DFS定义(它也适用于k元树):
struct Node
{
Node *parent = nullptr;
Node *left = nullptr;
Node *right = nullptr;
char data;
template<class Op1, class Op2, class Op3>
void depth_first_search(Op1 pre_order, Op2 in_order, Op3 post_order)
{
pre_order(*this);
if(this->left != nullptr && this->right != nullptr)
{
this->left->depth_first_search(pre_order, in_order, post_order);
in_order(*this);
this->right->depth_first_search(pre_order, in_order, post_order);
in_order(*this);
}
post_order(*this);
}
};
我可以使用以下代码来格式化此结构:
Formatter formatter(my_config);
tree.depth_first_search(formatter.get_pre_order(), formatter.get_in_order(), formatter.get_post_order());
auto result = formatter.take_result();
目标
由于它们工作得很好,当Boost图有树的值时,我想重用相同的函子来操作它们的格式。所以我尝试让这个(近似/错误)语法工作:
template<class Formatter>
class my_visitor : boost::default_dfs_visitor
{
Formatter & _formatter;
public:
my_visitor(Formatter& formatter) : _formatter(formatter){}
auto discover_vertex(auto vertex, auto const& g)
{
auto f = _formatter.get_pre_order();
f(vertex);
}
auto examine_edge(auto edge, auto const& g)
{
auto f = _formatter.get_in_order();
f(edge);
}
auto finish_vertex(auto vertex, auto const& g)
{
auto f = _formatter.get_post_order();
f(vertex);
}
};
因此,我可以使用如下语法格式化树
Formatter formatter(my_config);
my_visitor vis(formatter);
depth_first_search(graph, root, boost::visitor(vis));
auto s = formatter.take_result();
编号
在当前状态下,代码将在Gobolt上编译和运行:https://godbolt.org/z/bzjqjbvE3
然而,main函数中调用的最后一个方法(还)不存在,因为我不知道如何指定它:
auto s = newick::generate_from(tree);
有这样一个函数的注解草案,但我很难将其适配到BGL:
///
/// @brief Generate a Newick string from a k-ary tree with no properties attached to edges or vertices
///
std::string generate_from(quetzal::coalescence::k_ary_tree<> graph)
{
using vertex_t = typename quetzal::coalescence::k_ary_tree<>::vertex_descriptor;
// Data access
std::predicate<vertex_t> auto has_parent = [&graph](vertex_t v){ return graph.has_parent(v); };
std::predicate<vertex_t> auto has_children = [&graph](vertex_t v){ return graph.has_children(v); };
newick::Formattable<vertex_t> auto label = [&graph](auto){ return ""; };
newick::Formattable<vertex_t> auto branch_length = [&graph](auto){ return ""; };
// We declare a generator passing it the data interfaces
auto generator = newick::make_generator(has_parent, has_children, label, branch_length);
// We expose its interface to the boost DFS algorithm
detail::newick_no_property_visitor vis(generator);
depth_first_search(graph, boost::visitor(vis));
}
问题
我真的不能把我的头缠在界面一致性上,我很难确定问题的根源(哈哈):
- 我定义的pre/in/post操作是带有1个参数的可调用对象,具有
Node
语义(封装节点标识符和它所引用的图) - 而由BGL定义的访问者方法具有采用顶点+图或边+图参数的异构签名。
- 我也很难将前/中/后顺序操作Map到BGL访问者更复杂的界面。我认为
pre-order
Map到discover_vertex
,in_order
Map到examine_edge
,post_order
Map到finish_vertex
,尽管我不确定?
是否有办法协调这两个接口,或者它们的语义差异太大,我必须复制/修改格式化语法?
1条答案
按热度按时间jaxagkaj1#
下面是我的看法,我们不要生成随机图,而是复制用"老式
Node*
二元树"处理过的精确图:图纸
实现DFS访问者
关键是将"格式化程序"(
generator
)适当地 Package 到DFS访问者中。一些注意事项:
State
结构体中:旁注/错误
1.您在
has_parent()
和has_children()
中混淆了in_edges
和out_edges
,因此我将它们从:进入(略微现代化):
1.请注意,使用
in_edges
****不需要通过更改以下内容来更改为BidirectionalGraph模型变成
1.由于生成器操作与访问者事件的时间问题,我不得不在添加/删除逗号分隔符周围添加一些防护措施。我有一种感觉,如果您删除此区域的"阻抗不匹配",事情会变得更简单。
1.还有一些工作要做,您没有把它们放在这个问题的讨论范围内(好主意),这意味着实际上要对label/length函数进行泛化。
完整演示
图纸