520 likes | 536 Views
Extensible Tree. Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn. book. chap1. chap2. sec11. sec12. sec21. sec22. subsec111. Binary Tree. 10. 7. 15. 5. 8. 12. 37. 3. Binary Search Tree (BST). Extensible Tree. 1. 2. 3. 4. 5. 6. 7. 8.
E N D
Extensible Tree Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn
book chap1 chap2 sec11 sec12 sec21 sec22 subsec111 Binary Tree
10 7 15 5 8 12 37 3 Binary Search Tree (BST)
Extensible Tree 1 2 3 4 5 6 7 8
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 1 2 3 4 5 6 7 8
root depth=3 depth=0 depth=1 depth=2 internal node degree node siblings parent & child leaves Terminologies 1 2 3 4 5 6 7 8
9 Tree Extension 1 2 3 4 5 6 7 8
data t left right left data right Binary Tree Representation // For binary tree typedef struct btree *btree; struct btree { poly data; btree left; btree right; };
data child1 child2 childn ... t data child1 child2 … childn Extensible Tree // For general tree typedef struct tree *tree; struct tree { poly data; tree child1; tree child2; …; tree childn; }; // ugly and // not extensible
Extensible Tree Recall the graph representation: • Adjacency matrix • Adjacency list 0 1 2 3
Adjacency Matrix 0 1 2 3 0 2 3 1 0 1 2 3
Adjacency Matrix Extension 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
Adjacency List 0 1 2 3 0 1 2 3 1 2 3
Adjacency List Extension 0 1 2 3 4 0 1 2 3 4 1 2 3 4
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; }; 0 2 3 1 0 1 2 3
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; } 0 1 2 3 4 0 2 3 0 1 0 1 1 2 2 3 3 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; } 0 1 2 3 4 0 2 3 0 1 0 1 1 2 2 3 3 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 y z 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”); } 0 x y z 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”); } 0 x 1 y z 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”); } 0 x 1 2 y z 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”); } 0 x 3 1 2 y z 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”); } 0 x 3 1 2 y z 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”); } 0 x 3 1 2 y z 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”); } 0 x 3 1 2 y z 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; }
0 0->1 0->2 0->3 1 2 3 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 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; }
0 0->1 0->2 0->3 1 2 3 4 Tree Representation #2: Adjacency List void insertVertex (tree t, poly data) { vertex v = newVertex (data); linkedListInsertTail (t->vertices, v); return; }
0 0->1 0->2 0->3 1 2 3 4 Tree Representation #2: Adjacency List void insertVertex (tree t, poly data) { vertex v = newVertex (data); linkedListInsertTail (t->vertices, v); return; }
0 0->1 0->2 0->3 1 2 3 4 Tree Representation #2: Adjacency List void insertVertex (tree t, poly data) { vertex v = newVertex (data); linkedListInsertTail (t->vertices, v); return; }
0 0->1 0->2 0->3 1 2 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; }
0 0->1 0->2 0->3 1 2 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; }
0 0->1 0->2 0->3 1 2 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; }
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; } 0 0->1 0->2 0->3 0->4 1 2 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; } 0 0->1 0->2 0->3 0->4 1 2 3 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 y z u
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; } } }