/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { bool all_final = true; //for (BitSetIterator it=BitSetIterator(node->getLabeling());it!=BitSetIterator::end(node->getLabeling());++it) //BitSet label_this = node.getLabeling(); //for (int it = 0; it < label_this.Count; it++) for (int it = BitSetIterator.start(node.getLabeling()); it != BitSetIterator.end(node.getLabeling()); it = BitSetIterator.increment(node.getLabeling(), it)) { //// if (!_nba_states_with_all_succ_final.get(*it)) { if (!_nba_states_with_all_succ_final.get(it)) { all_final = false; break; } } if (all_final) { // remove all children of node & set final flag STVisitor_remove_subtree stv_remove = new STVisitor_remove_subtree(_tree_template); tree.walkChildrenPostOrder(stv_remove, node); node.setFinalFlag(); _success = true; } }
/** * Less-than operator when ignoring the node names. */ public bool structural_less_than(SafraTree other) { if (other.MAX_NODES < MAX_NODES) { return(true); } SafraTreeNode this_root = this.getRootNode(); SafraTreeNode other_root = other.getRootNode(); if (this_root == null) { if (other_root != null) { return(true); } else { return(false); } } else { // this_root !=0 if (other_root == null) { return(false); } return(this_root.structural_less_than(other_root)); } }
/** * Walk the subtree rooted under node *top (only the children, not *top itself) * post-order, calling the function void visit(SafraTree& tree, SafraTreeNode *node) * in the SafraTreeVisitor on each node. */ public void walkChildrenPostOrder(SafraTreeVisitor visitor, SafraTreeNode top) { SafraTreeWalker walker = new SafraTreeWalker(visitor); // = don't visit top walker.walkSubTreePostOrder(this, top, false); }
/** * Print the subtree rooted at node *top to the output stream * @param out the output stream * @param prefix the number of spaces ' ' in front of each node * @param top the current tree sub root */ public string printSubTree(int prefix, SafraTreeNode top) { string returnString = ""; for (int i = 0; i < prefix; i++) { returnString += " "; } returnString += top.ToString() + "\r\n"; //for (SafraTreeNode::child_iterator it=top->children_begin(); // it!=top->children_end(); // ++it) { // printSubTree(out, prefix+1, *it); //} SafraTreeNode it = top.children_begin(); while (it != top.children_end()) { printSubTree(prefix + 1, it); it = it.increment(); } return(returnString); }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { if (node.getChildCount() == 0) { return; } BitSet labeling_union = new BitSet(); //for (SafraTreeNode::child_iterator it=node->children_begin();it!=node->children_end();++it) SafraTreeNode it = node.children_begin(); while (it != node.children_end()) { labeling_union.Union(it.getLabeling()); it = it.increment(); } if (labeling_union == node.getLabeling()) { // The union of the labelings of the children is exactly the // same as the labeling of the parent -> // remove children STVisitor_remove_subtree stv_remove = new STVisitor_remove_subtree(_tree_template); tree.walkChildrenPostOrder(stv_remove, node); node.setFinalFlag(true);///////////should be "+ i", means in Li } }
// #define NULL_OR_EQUALID(a,b) ((a==0 && b==0) || ((a!=0 && b!=0) && (a.getID()==b.getID()))) ///** Equality operator. Does not do a deep compare */ //bool operator==(const SafraTreeNode& other) { // if (!(_id==other._id)) {return false;} // if (!(_final_flag==other._final_flag)) {return false;} // if (!(_childCount==other._childCount)) {return false;} // if (!(_labeling==other._labeling)) {return false;} // if (!NULL_OR_EQUALID(_parent, other._parent)) {return false;} // if (!NULL_OR_EQUALID(_olderBrother, other._olderBrother)) {return false;} // if (!NULL_OR_EQUALID(_youngerBrother, other._youngerBrother)) {return false;} // if (!NULL_OR_EQUALID(_oldestChild, other._oldestChild)) {return false;} // if (!NULL_OR_EQUALID(_youngestChild, other._youngestChild)) {return false;} // return true; //} /** * Equality operator ignoring the name of the nodes, doing a deep compare * (checks that all children are also structurally equal. */ public bool structural_equal_to(SafraTreeNode other) { if (!(_final_flag == other._final_flag)) { return(false); } if (!(_childCount == other._childCount)) { return(false); } if (!(_labeling == other._labeling)) { return(false); } if (_childCount > 0) { SafraTreeNode this_child = this._oldestChild; SafraTreeNode other_child = other._oldestChild; do { if (!this_child.structural_equal_to(other_child)) { return(false); } this_child = this_child._youngerBrother; other_child = other_child._youngerBrother; } while (this_child != null && other_child != null); System.Diagnostics.Debug.Assert(this_child == null && other_child == null); } return(true); }
/** Create a new node with name <i>id</i>. */ public SafraTreeNode newNode(int id) { Debug.Assert(id < MAX_NODES); Debug.Assert(_nodes[id] == null); _nodes[id] = new SafraTreeNode(id); return(_nodes[id]); }
public void hashCode(HashFunction hashfunction, bool only_structure) //only_structure=false { SafraTreeNode root = getRootNode(); if (root != null) { root.hashCode(hashfunction, only_structure); } }
/** * Return true if this tree (taking into account the renameableNames and the restrictedNames) * can be renamed to match the SafraTree other. * Can only be called for trees that are structural_equal!!! */ public bool matches(SafraTree other) { SafraTreeNode this_root = _safraTree.getRootNode(); SafraTreeNode other_root = other.getRootNode(); if (this_root == null || other_root == null) { Debug.Assert(this_root == null && other_root == null); return(true); } return(matches(this_root, other_root)); }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { BitSet new_labeling = new BitSet(); BitSet old_labeling = node.getLabeling(); for (int i = old_labeling.nextSetBit(0); i != -1; i = old_labeling.nextSetBit(i + 1)) { new_labeling.Union(_nba[i].getEdge(_elem));//////////////generate new label. } node.getLabeling().Assign(new_labeling); }
/** * Remove all children of the SafraTreeNode <i>id</i>. */ public void removeAllChildren(int id) { Debug.Assert(id < MAX_NODES); SafraTreeNode n = _nodes[id]; SafraTreeNode child; while ((child = n.getOldestChild()) != null) { removeAllChildren(child.getID()); remove(child.getID()); } }
/** */ public void visit(SafraTree tree, SafraTreeNode node) { if (_final_states.intersects(node.getLabeling()))//////////if this node has the state in accepting states of NBA { BitSet q_and_f = new BitSet(_final_states); q_and_f.Intersect(node.getLabeling());////////////////get the intersect of the label and the accepting states SafraTreeNode new_child = tree.newNode(); node.addAsYoungestChild(new_child); _tree_template.setRenameable(new_child.getID()); new_child.getLabeling().Assign(q_and_f); } }
/** * Compare two subtrees to see if they match (taking into account the renameableNames * and the restrictedNames). */ public bool matches(SafraTreeNode this_node, SafraTreeNode other_node) { Debug.Assert(this_node != null && other_node != null); if (this_node == null || other_node == null) { return(false); } if (!renameableNames().get(this_node.getID())) { // this is not a new node, so we require a perfect match.. if (other_node.getID() != this_node.getID()) { return(false); } } else { // we are flexible with the id, as long as the id wasn't removed // in the tree if (restrictedNames().get(other_node.getID())) { return(false); } } Debug.Assert(this_node.getLabeling() == other_node.getLabeling()); Debug.Assert(this_node.hasFinalFlag() == other_node.hasFinalFlag()); // this node looks good, now the children SafraTreeNode this_child = this_node.getOldestChild(); SafraTreeNode other_child = other_node.getOldestChild(); while (this_child != null && other_child != null) { if (!matches(this_child, other_child)) { return(false); } this_child = this_child.getYoungerBrother(); other_child = other_child.getYoungerBrother(); } Debug.Assert(this_child == null && other_child == null); return(true); }
/** Do a structural comparison */ private LEG structural_cmp(SafraTreeNode other) { LEG cmp = CMP(_final_flag ? 1 : 0, other._final_flag ? 1 : 0); if (cmp != LEG.EQUAL) { return(cmp); } cmp = CMP(_childCount, other._childCount); if (cmp != LEG.EQUAL) { return(cmp); } cmp = CMP(_labeling, other._labeling); if (cmp != LEG.EQUAL) { return(cmp); } // if we are here, this and other have the same number of children if (_childCount > 0) { SafraTreeNode this_child = this._oldestChild; SafraTreeNode other_child = other._oldestChild; do { cmp = this_child.structural_cmp(other_child); if (cmp != LEG.EQUAL) { return(cmp); } this_child = this_child._youngerBrother; other_child = other_child._youngerBrother; } while (this_child != null && other_child != null); // assert that there was really the same number of children System.Diagnostics.Debug.Assert(this_child == null && other_child == null); } // when we are here, all children were equal return(LEG.EQUAL); }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { int id = node.getID(); if (_tree_template.isRenameable(id)) { // this node was created recently, so we only delete it from // the renameableNames, but don't mark it in restrictedNames _tree_template.setRenameable(id, false); } else { _tree_template.setRestricted(id); } tree.remove(node); }
/** * Checks equality when ignoring the node names. */ public bool structural_equal_to(SafraTree other) { if (other.MAX_NODES != MAX_NODES) { return(false); } SafraTreeNode this_root = this.getRootNode(); SafraTreeNode other_root = other.getRootNode(); if (this_root == null || other_root == null) { // return true if both are 0 return(this_root == other_root); } return(this_root.structural_equal_to(other_root)); }
/** * Generate the appropriate acceptance signature for Rabin Acceptance for this tree */ public override void generateAcceptance(AcceptanceForState acceptance) { for (int i = 0; i < getNodeMax(); i++) { SafraTreeNode stn = this[i]; if (stn == null) { acceptance.addTo_U(i); } else { if (stn.hasFinalFlag()) { acceptance.addTo_L(i); } } } }
/** * Calculate a hashvalue using HashFunction for this node. * @param hashfunction the HashFunction functor * @param only_structure Ignore naming of the nodes? */ public void hashCode(HashFunction hashfunction, bool only_structure) //=false { if (!only_structure) { hashfunction.hash(getID()); } getLabeling().hashCode(hashfunction); hashfunction.hash(hasFinalFlag()); if (getChildCount() > 0) { //for (child_iterator cit=children_begin();cit!=children_end();++cit) for (SafraTreeNode cit = children_begin(); cit != children_end(); cit = cit.increment()) { cit.hashCode(hashfunction, only_structure); } } }
/** Add a node as the oldest child */ public void addAsOldestChild(SafraTreeNode other) { System.Diagnostics.Debug.Assert(other._parent == null); System.Diagnostics.Debug.Assert(other._olderBrother == null); System.Diagnostics.Debug.Assert(other._youngerBrother == null); if (_oldestChild != null) { System.Diagnostics.Debug.Assert(_oldestChild._olderBrother == null); _oldestChild._olderBrother = other; other._youngerBrother = _oldestChild; } other._parent = this; _oldestChild = other; if (_youngestChild == null) { _youngestChild = other; } _childCount++; }
/** Calculate the height of the subtree rooted at this node. */ public int treeHeight() { int height = 0; if (this._childCount > 0) { SafraTreeNode it = this._oldestChild; while (it != null) { SafraTreeNode cur_child = it; int child_height = cur_child.treeHeight(); if (child_height > height) { height = child_height; } it = it._youngerBrother; } } return(height + 1); }
/** Print HTML version of this node to output stream */ public string toHTML() { StringBuilder sb = new StringBuilder(); sb.Append("<TABLE><TR>"); if (getChildCount() <= 1) { sb.Append("<TD>"); } else { sb.Append("<TD COLSPAN=\""); sb.Append(getChildCount()); sb.Append("\">"); } sb.Append(getID()); sb.Append(" "); sb.Append(_labeling); if (_final_flag) { sb.Append("!"); } sb.Append("</TD></TR>"); if (getChildCount() > 0) { sb.Append("<TR>"); //for (child_iterator it = children_begin(); it != children_end(); ++it) for (SafraTreeNode cit = children_begin(); cit != children_end(); cit = cit.increment()) { sb.Append("<TD>"); sb.Append(cit.toHTML()); sb.Append("</TD>"); } sb.Append("</TR>"); } sb.Append("</TABLE>"); return(sb.ToString()); }
/** Remove this node from the tree (relink siblings). The node is not allowed to have children! */ public void removeFromTree() { System.Diagnostics.Debug.Assert(_childCount == 0); if (_parent == null) { // Root-Node or already removed from tree, nothing to do return; } // Relink siblings if (_olderBrother != null) { _olderBrother._youngerBrother = _youngerBrother; } if (_youngerBrother != null) { _youngerBrother._olderBrother = _olderBrother; } // Relink child-pointers in _parent if (_parent._oldestChild == this) { // this node is oldest child _parent._oldestChild = this._youngerBrother; } if (_parent._youngestChild == this) { // this node is youngest child _parent._youngestChild = this._olderBrother; } _parent._childCount = _parent._childCount - 1; _youngerBrother = null; _olderBrother = null; _parent = null; }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { if (node.getChildCount() <= 1) { return; } BitSet already_seen = new BitSet(); bool first = true; //for (SafraTreeNode::child_iterator it=node->children_begin();it!=node->children_end();++it) SafraTreeNode it = node.children_begin(); while (it != node.children_end()) { SafraTreeNode cur_child = it; if (first) { already_seen = new BitSet(cur_child.getLabeling()); ////////////get the NBA states in child first = false; it = it.increment(); ////////note added } else { BitSet current = new BitSet(cur_child.getLabeling()); BitSet intersection = new BitSet(already_seen); // make copy if (intersection.intersects(current)) { // There are some labels, which occur in older brothers, // remove them from current node and its children STVisitor_subtract_labeling stv_sub = new STVisitor_subtract_labeling(intersection); tree.walkSubTreePostOrder(stv_sub, cur_child); } already_seen.Union(current); it = it.increment(); } } }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { if (node.getChildCount() <= 1) { return; } BitSet already_seen = new BitSet(); bool first = true; //for (SafraTreeNode::child_iterator it=node->children_begin();it!=node->children_end();++it) SafraTreeNode it = node.children_begin(); while (it != node.children_end()) { SafraTreeNode cur_child = it; if (first) { already_seen = new BitSet(cur_child.getLabeling());////////////get the NBA states in child first = false; it = it.increment();////////note added } else { BitSet current = new BitSet(cur_child.getLabeling()); BitSet intersection = new BitSet(already_seen); // make copy if (intersection.intersects(current)) { // There are some labels, which occur in older brothers, // remove them from current node and its children STVisitor_subtract_labeling stv_sub = new STVisitor_subtract_labeling(intersection); tree.walkSubTreePostOrder(stv_sub, cur_child); } already_seen.Union(current); it = it.increment(); } } }
/** * Copy the subtree (the children) of *other * to *top, becoming the children of *top */ public void copySubTree(SafraTreeNode top, SafraTreeNode other) { if (other == null) { return; } //for (SafraTreeNode::child_iterator it=other->children_begin();it!=other->children_end();++it) { // SafraTreeNode *n=_nodes[(*it)->getID()], *n_o=*it; // top->addAsYoungestChild(n); // copySubTree(n, n_o); //} SafraTreeNode it = other.children_begin(); while (it != other.children_end()) { SafraTreeNode n = _nodes[it.getID()]; top.addAsYoungestChild(n); copySubTree(n, it); it = it.increment(); } }
public override void generateAcceptance(RabinSignature acceptance) { acceptance.setSize(getNodeMax()); for (int i = 0; i < getNodeMax(); i++) { SafraTreeNode stn = this[i]; if (stn == null) { acceptance.setColor(i, RabinColor.RABIN_RED); } else { if (stn.hasFinalFlag()) { acceptance.setColor(i, RabinColor.RABIN_GREEN); } else { acceptance.setColor(i, RabinColor.RABIN_WHITE); } } } }
/** Calculate the width of the subtree rooted at this node. */ public int treeWidth() { int width = 0; if (this._childCount > 0) { SafraTreeNode it = this._oldestChild; while (it != null) { SafraTreeNode cur_child = it; width += cur_child.treeWidth(); it = it._youngerBrother; } } else { width = 1; } return(width); }
private static bool CMP_ID(SafraTreeNode a, SafraTreeNode b) { if (a == null) { if (b != null) { return(true); } } else { if (b == null) { return(false); } if (a._id != b._id) { return(a._id < b._id); } } return(false); }
/** * Walk the subtree rooted under node *top post-order, * calling the function void visit(SafraTree& tree, SafraTreeNode *node) * in the SafraTreeVisitor on each node. */ public void walkSubTreePostOrder(SafraTreeVisitor visitor, SafraTreeNode top) { SafraTreeWalker walker = new SafraTreeWalker(visitor); walker.walkSubTreePostOrder(this, top); }
/** * Remove a SafraTreeNode from the tree, * the node can have no children. */ public void remove(SafraTreeNode node) { Debug.Assert(_nodes[node.getID()] == node); remove(node.getID()); }
/** Do a structural comparison */ private LEG structural_cmp(SafraTreeNode other) { LEG cmp = CMP(_final_flag ? 1 : 0, other._final_flag ? 1 : 0); if (cmp != LEG.EQUAL) { return cmp; } cmp = CMP(_childCount, other._childCount); if (cmp != LEG.EQUAL) { return cmp; } cmp = CMP(_labeling, other._labeling); if (cmp != LEG.EQUAL) { return cmp; } // if we are here, this and other have the same number of children if (_childCount > 0) { SafraTreeNode this_child = this._oldestChild; SafraTreeNode other_child = other._oldestChild; do { cmp = this_child.structural_cmp(other_child); if (cmp != LEG.EQUAL) { return cmp; } this_child = this_child._youngerBrother; other_child = other_child._youngerBrother; } while (this_child != null && other_child != null); // assert that there was really the same number of children System.Diagnostics.Debug.Assert(this_child == null && other_child == null); } // when we are here, all children were equal return LEG.EQUAL; }
/** * Print the subtree rooted at node *top to the output stream * @param out the output stream * @param prefix the number of spaces ' ' in front of each node * @param top the current tree sub root */ public string printSubTree(int prefix, SafraTreeNode top) { string returnString = ""; for (int i = 0; i < prefix; i++) { returnString += " "; } returnString += top.ToString() + "\r\n"; //for (SafraTreeNode::child_iterator it=top->children_begin(); // it!=top->children_end(); // ++it) { // printSubTree(out, prefix+1, *it); //} SafraTreeNode it = top.children_begin(); while (it != top.children_end()) { printSubTree(prefix + 1, it); it = it.increment(); } return returnString; }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { if (node.getChildCount() <= 1) { return; } int i = 0; //for (SafraTreeNode::child_iterator it= node->children_begin(); it!=node->children_end();++it) SafraTreeNode it = node.children_begin(); while (it != node.children_end()) { BitSet reachable_this = _node_reachability[it.getID()]; reachable_this.clear(); _node_order[it.getID()] = i++; BitSet label_this = it.getLabeling(); //for (BitSetIterator label_it(label_this); label_it != BitSetIterator::end(label_this); ++label_it) for (int label_it = 0; label_it < label_this.Count; label_it++) { reachable_this.Union(_nba_reachability[label_it]); } // std::cerr << "reachability_this: "<<reachable_this << std::endl; it = it.increment(); } // reorder... // std::cerr << "Sorting!" << std::endl; // Bubble sort, ough! bool finished = false; while (!finished) { finished = true; for (SafraTreeNode a = node.getOldestChild(); a != null && a.getYoungerBrother() != null; a = a.getYoungerBrother()) { SafraTreeNode b = a.getYoungerBrother(); BitSet reach_a = _node_reachability[a.getID()]; BitSet reach_b = _node_reachability[b.getID()]; if (reach_a.intersects(reach_b)) { // a and b are not independant... // --> keep relative order... System.Diagnostics.Debug.Assert(_node_order[a.getID()] < _node_order[b.getID()]); } else { // a and b are independant... if (!(a.getLabeling() < b.getLabeling())) { // swap node.swapChildren(a, b); a = b; finished = false; } } } } }
public void visit(SafraTree tree, SafraTreeNode node) { node.getLabeling().Minus(_bitset); }
/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { node.setFinalFlag(false); }
/** * Less-than operator ignoring the name of the nodes, doing a deep compare * (applies recursively on the children). */ public bool structural_less_than(SafraTreeNode other) { return (this.structural_cmp(other) == LEG.LESS); }
/** * Swap the places of two child nodes */ public void swapChildren(SafraTreeNode a, SafraTreeNode b) { System.Diagnostics.Debug.Assert(a._parent == b._parent && a._parent == this); if (a == b) { return; } if (_oldestChild == a) { _oldestChild = b; } else if (_oldestChild == b) { _oldestChild = a; } if (_youngestChild == a) { _youngestChild = b; } else if (_youngestChild == b) { _youngestChild = a; } SafraTreeNode a_left = a._olderBrother, b_left = b._olderBrother, a_right = a._youngerBrother, b_right = b._youngerBrother; if (a_left != null) { a_left._youngerBrother = b; } if (b_left != null) { b_left._youngerBrother = a; } if (a_right != null) { a_right._olderBrother = b; } if (b_right != null) { b_right._olderBrother = a; } a._olderBrother = b_left; a._youngerBrother = b_right; b._olderBrother = a_left; b._youngerBrother = a_right; if (a_right == b) { // a & b are direct neighbours, a to the left of b a._olderBrother = b; b._youngerBrother = a; } else if (b_right == a) { // a & b are direct neighbours, b to the left of a a._youngerBrother = b; b._olderBrother = a; } }
private static bool CMP_ID(SafraTreeNode a, SafraTreeNode b) { if (a == null) { if (b != null) { return true; } } else { if (b == null) { return false; } if (a._id != b._id) { return a._id < b._id; } } return false; }
/** Create a new node with name <i>id</i>. */ public SafraTreeNode newNode(int id) { Debug.Assert(id < MAX_NODES); Debug.Assert(_nodes[id] == null); _nodes[id] = new SafraTreeNode(id); return _nodes[id]; }
private static bool NULL_OR_EQUALID(SafraTreeNode a, SafraTreeNode b) { return (a == null && b == null) || ((a != null && b != null) && (a._id == b._id)); }
// #define NULL_OR_EQUALID(a,b) ((a==0 && b==0) || ((a!=0 && b!=0) && (a.getID()==b.getID()))) ///** Equality operator. Does not do a deep compare */ //bool operator==(const SafraTreeNode& other) { // if (!(_id==other._id)) {return false;} // if (!(_final_flag==other._final_flag)) {return false;} // if (!(_childCount==other._childCount)) {return false;} // if (!(_labeling==other._labeling)) {return false;} // if (!NULL_OR_EQUALID(_parent, other._parent)) {return false;} // if (!NULL_OR_EQUALID(_olderBrother, other._olderBrother)) {return false;} // if (!NULL_OR_EQUALID(_youngerBrother, other._youngerBrother)) {return false;} // if (!NULL_OR_EQUALID(_oldestChild, other._oldestChild)) {return false;} // if (!NULL_OR_EQUALID(_youngestChild, other._youngestChild)) {return false;} // return true; //} /** * Equality operator ignoring the name of the nodes, doing a deep compare * (checks that all children are also structurally equal. */ public bool structural_equal_to(SafraTreeNode other) { if (!(_final_flag == other._final_flag)) { return false; } if (!(_childCount == other._childCount)) { return false; } if (!(_labeling == other._labeling)) { return false; } if (_childCount > 0) { SafraTreeNode this_child = this._oldestChild; SafraTreeNode other_child = other._oldestChild; do { if (!this_child.structural_equal_to(other_child)) { return false; } this_child = this_child._youngerBrother; other_child = other_child._youngerBrother; } while (this_child != null && other_child != null); System.Diagnostics.Debug.Assert(this_child == null && other_child == null); } return true; }
/** Add a node as the youngest child */ public void addAsYoungestChild(SafraTreeNode other) { System.Diagnostics.Debug.Assert(other._parent == null); System.Diagnostics.Debug.Assert(other._olderBrother == null); System.Diagnostics.Debug.Assert(other._youngerBrother == null); if (_youngestChild != null) { System.Diagnostics.Debug.Assert(_youngestChild._youngerBrother == null); _youngestChild._youngerBrother = other; other._olderBrother = _youngestChild; } other._parent = this; _youngestChild = other; if (_oldestChild == null) { _oldestChild = other; } _childCount++; }