Extensible Tree Discrete Mathematics and Its Applications Baojian Hua
Binary Tree book chap1chap2 sec11 sec12sec21 subsec111 sec22
Binary Search Tree (BST)
Extensible Tree
Definition of Extensible Tree An extensible tree is a collection of nodes: there exists a unique root node r other nodes are classified into n (n>=0) disjoint sets T_1, …, T_n, and every T_i is also a tree. T_1, …, T_n are called sub-trees of r. Moral: n may not be determined statically (dynamically extensible) Recursive definition Sub-trees disjoint
In Graph unique root
Terminologies node degree leaves root internal node parent & child siblings depth=1 depth=0 depth=2 depth=3
Tree Extension
Binary Tree Representation // For binary tree typedef struct btree *btree; struct btree { poly data; btree left; btree right; }; t leftdataright data leftright
Extensible Tree // For general tree typedef struct tree *tree; struct tree { poly data; tree child1; tree child2; …; tree childn; }; // ugly and // not extensible data child1childnchild2... t datachild1child2childn …
Extensible Tree Recall the graph representation: 1. Adjacency matrix 2. Adjacency list
Adjacency Matrix ###
Adjacency Matrix Extension #### 4 4
Adjacency List
Adjacency List Extension
Extensible Tree in C
Abstract Data Types in C: Interface // in file “tree.h” #ifndef TREE_H #define TREE_H typedef struct btree *btree; typedef void (*visitTy) (poly); tree newTree (); void insertVertex (tree t, poly v); void insertEdge (tree t, poly from, poly to); void preOrder (btree t, poly r, visitTy visit); void levelOrder (btree t, poly r, visitTy visit); #endif
Tree Implementation #1: Adjacency Matrix // adjacency matrix-based implementation #include “matrix.h” #include “hash.h” #include “tree.h” struct tree { matrix matrix; // remember the index hash hash; }; ###
Matrix Interface // file “matrix.h” #ifndef MATRIX_H #define MATRIX_H typedef struct matrix *matrix; matrix newMatrix (); void matrixInsert (matrix m, int i, int j); int matrixExtend (matrix m); #endif // Implementation could make use of a two- // dimensional extensible array, leave to you.
Tree Implementation #1: Adjacency Matrix tree newTree () { tree t = malloc (sizeof (*t)); t->matrix = newMatrix (); // an empty matrix t->hash = newHash (); return t; }
Tree Implementation #1: Adjacency Matrix void insertVertex (tree t, poly v) { int i = matrixExtend (t->matrix); hashInsert (t->hash, v, i); return; } ### ### 4 4
Tree Implementation #1: Adjacency Matrix void insertEdge (tree t, poly from, poly to) { int f = hashLookup (t->hash, from); int t = hashLookup (t->hash, to); matrixInsert (t->matrix, f, t); return; } ### #### 4 4
How to build a tree? Starting from an empty tree t Insert all vertices Insert all edges
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u 0
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u 0 1
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u 0 12
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u
Tree Representation #2: Adjacency List #include “linkedList.h” #include “tree.h” struct tree{ linkedList vertices; }; typedef struct vertex *vertex; typedef struct edge *edge; struct vertex { poly data; linkedList edges; }; struct edge { vertex from; vertex to; }
Tree Representation #2: Adjacency List #include “linkedList.h” #include “tree.h” struct tree{ linkedList vertices; }; typedef struct vertex *vertex; typedef struct edge *edge; struct vertex { poly data; linkedList edges; }; struct edge { vertex from; vertex to; } >10->20->3
Tree Representation #2: Adjacency List tree newTree () { tree t = malloc (sizeof (*t)); t->vertices = newLinkedList (); return t; }
Tree Representation #2: Adjacency List // but we’ve vertices and edges vertex newVertex (poly data) { vertex v = malloc (sizeof (*v)); v->data = data; v->edges = newLinkedList (); return v; }
Tree Representation #2: Adjacency List // but we’ve vertices and edges edge newEdge (vertex from, vertex to) { edge e = malloc (sizeof (*e)); e->from = from; e->to = to; return e; }
Tree Representation #2: Adjacency List void insertVertex (tree t, poly data) { vertex v = newVertex (data); linkedListInsertTail (t->vertices, v); return; } >10->20->3 4
Tree Representation #2: Adjacency List void insertVertex (tree t, poly data) { vertex v = newVertex (data); linkedListInsertTail (t->vertices, v); return; } >10->20->3 4
Tree Representation #2: Adjacency List void insertVertex (tree t, poly data) { vertex v = newVertex (data); linkedListInsertTail (t->vertices, v); return; } >10->20->3 4
Tree Representation #2: Adjacency List void insertEdge (tree t, poly from, poly to) { vertex vf = lookupVertex (t, from); vertex vt = lookupVertex (t, to); edge e = newEdge (vf, vt); linkedListInsertTail (vf->edges, e); return; } >10->20->3 4
Tree Representation #2: Adjacency List void insertEdge (tree t, poly from, poly to) { vertex vf = lookupVertex (t, from); vertex vt = lookupVertex (t, to); edge e = newEdge (vf, vt); linkedListInsertTail (vf->edges, e); return; } >10->20->3 4
Tree Representation #2: Adjacency List void insertEdge (tree t, poly from, poly to) { vertex vf = lookupVertex (t, from); vertex vt = lookupVertex (t, to); edge e = newEdge (vf, vt); linkedListInsertTail (vf->edges, e); return; } >10->20->3 4
Tree Representation #2: Adjacency List void insertEdge (tree t, poly from, poly to) { vertex vf = lookupVertex (t, from); vertex vt = lookupVertex (t, to); edge e = newEdge (vf, vt); linkedListInsertTail (vf->edges, e); return; } >10->20->3 4 0->4
Tree Representation #2: Adjacency List void insertEdge (tree t, poly from, poly to) { vertex vf = lookupVertex (t, from); vertex vt = lookupVertex (t, to); edge e = newEdge (vf, vt); linkedListInsertTail (vf->edges, e); return; } >10->20->3 4 0->4
Client Code int main () { tree t = newTree (); insertVertex (t, “x”); insertVertex (t, “y”); insertVertex (t, “z”); insertVertex (t, “u”); insertEdge (t, “x”, “y”); insertEdge (t, “x”, “z”); insertEdge (t, “x”, “u”); } x yz u
Tree Traversal
Abstract Data Types in C: Interface // in file “tree.h” #ifndef TREE_H #define TREE_H typedef struct btree *btree; typedef void (*visitTy) (poly); tree newTree (); void insertVertex (tree t, poly v); void insertEdge (tree t, poly from, poly to); void preOrder (btree t, poly r, visitTy visit); void levelOrder (btree t, poly r, visitTy visit); #endif
Pre-order Traversal void preOrder (tree t, poly r, visitTy visit) { vertex rv = lookupVertex (t, r); visit (rv->data); linkedList edges = rv->edges; while (edges) { preOrder (t, edges->data->to, visit); edges = edges->next; } return; } // try isit = printf // in-order and post-order similar
Moral preOrder is a recursive algorithm: defined on recursively defined data structures system (machine) keeps a stack to control the recursive order Generally, recursion are more elegant, easy- to-write and easy-to-reason than corresponding iterative ones A powerful programming idiom to recommend Some languages even encourage this by removing “ while ” and “ for ” completely
Level-order Traversal void levelOrder (tree t, poly r, visitTy visit) { queue q = newQueue (); vertex vr = lookupVertex (t, r); enQueue (q, vr); while (! queueIsEmpty(q)) { vertex x = deQueue (q); visit (x->data); linkeList edges = x->edges; while (edges){ enQueue (q, edges->data->to); edges = edges->next; }
Moral Pre-order traversal ==> depth first searching (dfs) Level-order traversal ==> breath first search (bfs)
Summary Extensible tree is a beautiful and elegant data structure every vertex has arbitrary number of children structure is inductively defined In all cases, such a data structure is worth of recommendation Could be generalized to graphs Next class