def remove_subtree(self, nid): """ Return a subtree deleted from this tree. If nid is None, an empty tree is returned. For the original tree, this method is similar to `remove_node(self,nid)`, because given node and its children are removed from the original tree in both methods. For the returned value and performance, these two methods are different: `remove_node` returns the number of deleted nodes; `remove_subtree` returns a subtree of deleted nodes; You are always suggested to use `remove_node` if your only to delete nodes from a tree, as the other one need memory allocation to store the new tree. """ st = Tree() if nid is None: return st if not self.contains(nid): raise NodeIDAbsentError("Node '%s' is not in the tree" % nid) st.root = nid parent = self[nid].bpointer self[nid].bpointer = None # reset root parent for the new tree removed = [] for id in self.expand_tree(nid): removed.append(id) for id in removed: st._nodes.update({id: self._nodes.pop(id)}) # Update its parent info self.__update_fpointer(parent, nid, Node.DELETE) return st
def subtree(self, nid): """ Return a shallow COPY of subtree with nid being the new root. If nid is None, return an empty tree. If you are looking for a deepcopy, please create a new tree with this shallow copy, e.g. new_tree = Tree(t.subtree(t.root), deep=True) This line creates a deep copy of the entire tree. """ st = Tree() if nid is None: return st if not self.contains(nid): raise NodeIDAbsentError("Node '%s' is not in the tree" % nid) st.root = nid for node_n in self.expand_tree(nid): st._nodes.update({self[node_n].identifier: self[node_n]}) return st