E N D
General Trees • A tree T is a finite set of one or more nodes such that there is one designated node r called the root of T, and the remaining nodes in (T-{r}) are partitioned into n0 disjoint subsets T1, T2, …, Tk, each of which is a tree, and whose roots r1, r2, …, rk, respectively, are children of r.
General Tree Example Root R Ancestors of V P V S1 S2 C1 C2 Siblings of V Children of V Subtree rooted at V
ADT of General Tree Node class Gtnode{ public: GTnode(const ELEM); ~GTnode(); ELEM value(); bool isLeaf(); GTnode * parent(); GTnode* leftmost_child(); GTnode* right_sibling(); void setValue(ELEM); void insert_first(GTnode *); void insert_next(GTnode *); void remove_first(); void remove_next(); };
ADT General Tree and Traversal class GenTree{ public: GenTree(); ~GenTree(); void clear(); GTnode * root(); void newroot(ELEM, GTnode *, GTnode *); }; void print(Gtnode * root) { if (root->isLeaf()) cout<<“Leaf:”; else cout<<“Internal:”; cout<<root->value()<<endl; Gtnode * temp=root->leftmost_child(); while (temp!=NULL) {print(temp); temp=temp->right_sibling();}}
Parent Pointer Implementation R W A B X Y Z C D E F
Why Parent Pointer? • Parent Pointer is good for answering the question: Are these two nodes in the same tree? Bool Gentree::sametree(int a, int b){ Gtnode * root1=a; Gtnode * root2=b; while (parent[root1] != -1) root1=parent[root1]; while (parent[root2] != -1) root2=parent[root2]; return root1 == root2; }
Equivalence Classes • A set of items that are “equivalent”. • The sets of equivalence classes are mutually exclusive. • When 2 items are found to be equivalent, you want to union the two sets containing these items. • If both items are already in the same set, then no need to do anything. • When joining the 2 sets, want to keep the depth small. • Join the tree with fewer nodes to the tree with more nodes. • Path compression: want all nodes to point to the root.
Implementations of General Trees • Lists of Children - Use an array of structures. Each element has the data, a parent pointer and a pointer to a list of pointers to the children of that node. • Easy to find leftmost child • To find a node’s sibling, first go to his parent, then go through the child list until you find a pointer to that node, the next node is his sibling. • Easy to combine trees if using just one array, difficult if using several arrays. • Left Child/Right Sibling - Each node has a pointer to his leftmost child and a pointer to his right sibling (can also have a parent pointer). • Easy to find parent, leftmost child and right sibling. • Easy to combine trees if in same array.
Dynamic Node Implementation • Allocate variable space for node for the number of children pointers. • Difficult to change (add or delete children). • Assumes know the number of children when creating. • Keep a linked list of children pointers since do not know the number of children. • Same as Lists of Children method. • Dynamic Left Child/Right Sibling method. • Each node has 2 or 3 pointers (left child, right sibling, parent). • Easy to work with forests • K-ary trees - Have a fixed number of pointers in each node. • Large number of null pointers as K gets bigger.