diff --git a/main.cpp b/main.cpp index f770c6bf78225d77d96b7757ff412e021909520c..cd7a910ee3ac2c8c8b1cd7053ad10af1be46de6a 100644 --- a/main.cpp +++ b/main.cpp @@ -103,12 +103,7 @@ TEST(cell_tree, from_parent_index) { EXPECT_EQ(tree.num_children(3), 0); EXPECT_EQ(tree.num_children(4), 0); } -} - -TEST(cell_tree, test_balance) { { - // a cell with the following structure - // should be rebalanced around node 1 // 0 // / \ // 1 2 @@ -131,6 +126,25 @@ TEST(cell_tree, test_balance) { } } +TEST(tree, change_root) { + { + // a cell with the following structure + // should be rebalanced around node 1 + // 0 + // / \ + // 1 2 + // / \ + // 3 4 + // / \ + // 5 6 + std::vector<int> parent_index = {0,0,0,1,1,4,4}; + tree t; + t.init_from_parent_index(parent_index); + + auto new_tree = t.change_root(1); + } +} + /* void test_json() { json cell_data; diff --git a/tree.hpp b/tree.hpp index 6437ed3225e5dbf04b21861ed78b7e4e7c83fc69..a887234a4cd76bbbfab377ed8fcf938792b19a15 100644 --- a/tree.hpp +++ b/tree.hpp @@ -175,6 +175,34 @@ class tree { return sizeof(int_type)*data_.size() + sizeof(tree); } + tree change_root(int b) const { + assert(b<num_nodes()); + + // no need to rebalance if the root node has been requested + if(b==0) { + return tree(*this); + } + + // create new tree with memory allocated + tree new_tree; + new_tree.init(num_nodes()); + + // add the root node + //new_tree.parents_[0] = -1; + new_tree.child_index_[0] = 0; + + // allocate space for the permutation vector that + // will represent the permutation performed on the branches + // during the rebalancing + index_type p(num_nodes()+1); + std::cout << "allocated for array of size " << p.size() << std::endl; + + // recersively rebalance the tree + new_tree.add_children(0, b, p, *this, true); + + return new_tree; + } + private : void init(int nnode) { @@ -200,58 +228,70 @@ class tree { assert(parents_.size() == nnode); } - /// Renumber the sub-tree with old_branch as its root with new_branch as - /// the new index of old_branch. This is a helper function for the + /// Renumber the sub-tree with old_node as its root with new_node as + /// the new index of old_node. This is a helper function for the /// renumbering required when a new root node is chosen to improve /// the balance of the tree. - /// Optionally add the parent of old_branch as a child of new_branch, which + /// Optionally add the parent of old_node as a child of new_node, which /// will be applied recursively until the old root has been processed, /// which indicates that the renumbering is finished. - /* - int add_child( int new_branch, int old_branch, index_view p, - bool parent_as_child) + /// + /// precondition - the node new node has already been placed in the tree + int add_children( + int new_node, + int old_node, + index_view p, + tree const& old_tree, + bool parent_as_child + ) { + std::cout << "add_children(old " << old_node << ", new " << new_node << ", " << parent_as_child << ")" << std::endl; + // check for the senitel that indicates that the old root has // been processed - if(old_branch==-1) { + if(old_node==-1) { assert(parent_as_child); // sanity check - return new_branch; + return new_node; } - auto kids = children(old_branch); - auto pos = new_child_index[new_branch]; + auto old_children = old_tree.children(old_node); + auto pos = child_index_[new_node]; - new_child_index[new_branch+1] = pos + kids.size(); - // add an extra one if adding the parent as a child - if(parent_as_child) { - ++new_child_index[new_branch+1]; - } + auto n_children = old_children.size() + (parent_as_child ? 1 : 0); + child_index_[new_node+1] = pos + n_children; + std::cout << " inserting " << n_children << " into " << child_index_(new_node, new_node+2) << std::endl; + std::cout << " inserting"; // first renumber the children - for(auto b : kids) { - p[new_branch] = b; - new_children[pos++] = new_branch++; + for(auto b : old_children) { + std::cout << " " << b; + new_node++; + p[new_node] = b; + children_[pos++] = new_node; } // then add and renumber the parent as a child if(parent_as_child) { - p[new_branch] = parents_[old_branch]; - new_children[pos++] = new_branch++; + std::cout << " " << yellow(std::to_string(old_tree.parent(old_node))); + new_node++; + p[new_node] = old_tree.parent(old_node); + children_[pos++] = new_node; } + std::cout << std::endl; // then visit the sub-tree of each child recursively // - traverse _down_ the tree - for(auto b : kids) { - new_branch = add_children(new_branch, b, p, false); + //auto child_range = range(); + for(auto b : old_children) { + new_node = add_children(new_node, b, p, old_tree, false); } // finally visit the parent recursively // - traverse _up_ the tree towards the old root if(parent_as_child) { - new_branch = add_children(new_branch, parents_[old_branch], p, true); + new_node = add_children(new_node, parents_[old_node], p, old_tree, true); } - return new_branch; + return new_node; } - */ index_type data_; index_view children_;