Я использую tree.hh реализация. У меня есть простое «дерево», подобное следующему (A, B и C — братья и сестры без родителей, B1 — дочерний элемент для B):
A
B
B1
C
Теперь я хочу «переместить» C, чтобы он также был потомком B. Я попробовал следующий минимальный пример, но не нашел простого способа сделать это, используя методы в tree.hh.
Единственное решение, которое я нашел, было:
#include <iostream>
#include "tree.hh"#include "tree_util.hh"
void print_tree(const tree<std::string>& tr)
{
tree<std::string>::pre_order_iterator it = tr.begin();
tree<std::string>::pre_order_iterator end = tr.end();
if(!tr.is_valid(it)) return;
int rootdepth=tr.depth(it);
std::cout << "-----" << std::endl;
while(it!=end) {
for(int i=0; i<tr.depth(it)-rootdepth; ++i)
std::cout << " ";
std::cout << (*it) << std::endl << std::flush;
++it;
}
std::cout << "-----" << std::endl;
}
int main(int, char **)
{
tree<std::string> my_tree;
tree<std::string>::iterator iA = my_tree.insert(my_tree.end(), "A");
tree<std::string>::iterator iB = my_tree.insert(my_tree.end(), "B");
tree<std::string>::iterator iB1 = my_tree.append_child(iB, "B1");
tree<std::string>::iterator iC = my_tree.insert(my_tree.end(), "C");
print_tree(my_tree);
// this makes a copy of "C" --> not what I want
auto iC_append = my_tree.append_child(iB, iC);
print_tree(my_tree);
my_tree.erase(iC_append);
// this extracts "C" into a separate tree and then appends the tree as child to "B"tree<std::string> sub_tree = my_tree.move_out(iC);
my_tree.move_in_as_nth_child(iB, my_tree.number_of_children(iB), sub_tree);
print_tree(my_tree);
}
Сомневаюсь, что это самое простое из возможных решений. Есть идеи, что я делаю не так?
Спасибо!
Ура,
Джонатан
использование move_after
, как в
my_tree.move_after(iB1, iC);
Это перемещает узел в iC
(и любые дети, если они есть), чтобы стать родным братом B
,
Это заняло некоторое время, но я думаю, что нашел — по крайней мере выполнимый и более или менее надежный — ответ.
Сначала я добавляю пустой дочерний узел к желаемому новому родителю. Тогда я использую ::move_ontop()
сделать мой желаемый дочерний узел (плюс его дочерние элементы) заменой пустого дочернего узла из предыдущего шага.
Таким образом, мой приведенный выше пример теперь выглядит следующим образом (для проверки правильности перемещения всех детей я ввел дополнительный дочерний узел C1 как дочерний для C):
#include <iostream>
#include <string>
#include "tree.hh"#include "tree_util.hh"
void print_tree(const tree<std::string>& tr)
{
tree<std::string>::pre_order_iterator it = tr.begin();
tree<std::string>::pre_order_iterator end = tr.end();
if (!tr.is_valid(it)) return;
int rootdepth = tr.depth(it);
std::cout << "-----" << std::endl;
while (it != end) {
for (int i = 0; i<tr.depth(it) - rootdepth; ++i)
std::cout << " ";
std::cout << (*it) << std::endl << std::flush;
++it;
}
std::cout << "-----" << std::endl;
}
int main(int, char **)
{
tree<std::string> my_tree;
tree<std::string>::iterator iA = my_tree.insert(my_tree.end(), "A");
tree<std::string>::iterator iB = my_tree.insert(my_tree.end(), "B");
tree<std::string>::iterator iB1 = my_tree.append_child(iB, "B1");
tree<std::string>::iterator iC = my_tree.insert(my_tree.end(), "C");
tree<std::string>::iterator iC1 = my_tree.append_child(iC, "C1");
print_tree(my_tree);
// First append an empty-child to the desired parent...
auto iNew = my_tree.append_child(iB);
// ...and then "squash" the empty child with the source child (and sub-children)
iC = my_tree.move_ontop(iNew, iC);
print_tree(my_tree);
}
Вывод теперь, по желанию:
-----
A
B
B1
C
C1
-----
-----
A
B
B1
C
C1
-----