39 #include <unordered_map>
40 #include <unordered_set>
50 struct TreeTableHelpers
53 std::unordered_map<std::string, size_t> name_to_index;
56 std::unordered_set<std::string> child_names;
57 std::unordered_set<std::string> parent_names;
61 TreeTableHelpers& helpers,
62 std::string
const& child_name,
63 std::string
const& parent_name,
67 if( helpers.child_names.count( child_name ) > 0 ) {
68 throw std::runtime_error(
69 "Node name \"" + child_name +
"\" appears multiple times as a child node"
72 helpers.child_names.insert( child_name );
73 helpers.parent_names.insert( parent_name );
81 auto add_named_node_ = [&]( std::string
const& node_name )
84 auto const node_index = nodes.size();
88 auto new_node = utils::make_unique< TreeNode >();
89 new_node->reset_index( node_index );
94 nodes.push_back( std::move( new_node ));
95 helpers.name_to_index[ node_name ] = node_index;
102 bool is_new_parent =
false;
103 if( helpers.name_to_index.count( parent_name ) == 0 ) {
104 add_named_node_( parent_name );
105 is_new_parent =
true;
109 bool is_new_child =
false;
110 if( helpers.name_to_index.count( child_name ) == 0 ) {
111 add_named_node_( child_name );
116 auto* parent_node = &tree.
node_at( helpers.name_to_index[ parent_name ]);
117 auto* child_node = &tree.
node_at( helpers.name_to_index[ child_name ]);
123 auto parent_link = utils::make_unique< TreeLink >();
124 auto child_link = utils::make_unique< TreeLink >();
125 auto new_edge = utils::make_unique< TreeEdge >();
130 parent_link->reset_index( links.size() );
131 if( is_new_parent ) {
132 parent_link->reset_next( parent_link.get() );
133 parent_node->reset_primary_link( parent_link.get() );
135 parent_link->reset_next( &parent_node->primary_link().next() );
136 parent_node->primary_link().reset_next( parent_link.get() );
138 parent_link->reset_outer( child_link.get() );
139 parent_link->reset_node( parent_node );
140 parent_link->reset_edge( new_edge.get() );
145 child_link->reset_index( links.size() + 1 );
147 child_link->reset_next( child_link.get() );
148 child_node->reset_primary_link( child_link.get() );
150 child_link->reset_next( &child_node->primary_link().next() );
151 child_node->primary_link().reset_next( child_link.get() );
152 child_node->reset_primary_link( child_link.get() );
154 child_link->reset_outer( parent_link.get() );
155 child_link->reset_node( child_node );
156 child_link->reset_edge( new_edge.get() );
159 new_edge->reset_index( edges.size() );
160 new_edge->reset_primary_link( parent_link.get() );
161 new_edge->reset_secondary_link( child_link.get() );
165 links.push_back( std::move( parent_link ));
166 links.push_back( std::move( child_link ));
167 edges.push_back( std::move( new_edge ));
171 std::vector<std::string>
const& child_names,
172 std::vector<std::string>
const& parent_names
174 if( child_names.size() != parent_names.size() ) {
175 throw std::runtime_error(
176 "Cannot create tree from parents table with different number of entries in columns"
179 if( child_names.empty() ) {
188 TreeTableHelpers helpers;
189 for(
size_t i = 0; i < parent_names.size(); ++i ) {
191 helpers, child_names[i], parent_names[i], tree
199 std::vector<std::string> root_nodes;
200 for(
auto& node : tree.
nodes() ) {
206 if( root_nodes.size() != 1 ) {
207 throw std::invalid_argument(
208 "Provided list of child and parent nodes does not form a singe tree, but a forest with " +
212 assert( tree.
node_count() == child_names.size() + 1 );