在tree.hh中将任意节点及其子节点作为子节点移动

时间:2018-01-02 16:49:24

标签: c++ tree parent-child children appendchild

我正在使用tree.hh实施。我有一个简单的"树"如下所示(A,B和C是没有父母的兄弟姐妹,B1是B的孩子):

A
B
  B1
C

现在我想"移动" C也是B的孩子。我尝试了以下最小的例子,但没有找到一种简单的方法来使用tree.hh中的方法来做到这一点。

我找到的唯一解决方案是:

  1. 从C及其子项中提取子树(将其从原始树中删除)
  2. 将C子树作为子树附加到所需的新父B
  3. See code on pastebin.com

    #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);
    }
    

    我怀疑,这是最简单的解决方案。我有什么想法吗?

    谢谢!

    干杯, 乔纳森

2 个答案:

答案 0 :(得分:1)

使用move_after,如

my_tree.move_after(iB1, iC);

这会移动iC处的节点(以及任何子节点,如果存在)成为B的兄弟节点。

答案 1 :(得分:0)

花了一些时间,但我认为我找到了一个 - 至少可行且更强或更不健全 - 答案。

我首先将空子节点附加到所需的新父节点。然后我使用::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
-----