Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Tree C and Data Structures Baojian Hua [email protected] What’ s a Tree? book chap1 sec11 subsec111 chap2 sec12 chap3 sec21 Definition of Tree A tree is a collection of nodes, which satisfies: 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: Recursive definition Sub-trees disjoint What’ s a Tree? unique root book chap1 sec11 subsec111 chap2 sec12 chap3 sec21 Terminologies depth=0 root book internal node chap1 depth=1 chap2 chap3 degree depth=2 node & child parent sec11 sec12 sec21 depth=3 siblings subsec111 leaves Binary Tree A binary tree is a collection of nodes, which satisfies: there exists a unique root node r other nodes are classified into n (0<=n<=2) disjoint ordered sets T_1, …, T_n, and every set T_i is also a binary tree. To note: 0<=Degree(any node)<=2 the order of sub-tree is relevant Examples book chap1 sec11 subsec111 book chap1 sec11 subsec111 chap2 sec12 sec21 sec22 Properties of Binary Tree Properties of Binary Tree Full and Complete Binary Tree A full binary tree is a binary tree of depth k and 2^{k+1}-1 nodes each node either has degree 2 (internal nodes) or degree 0 (leaves) A n-node complete binary tree is a tree with nodes number of full binary tree Abstract Data Types in C: Interface // in file “btree.h” #ifndef BTREE_H #define BTREE_H typedef struct btreeStruct *btree; btree newTree (); btree newTree2 (btree left, btree right, poly data); void insert (btree t, poly parent, poly child, char pos); void preOrder (btree t, void (*visit)(poly)); void inOrder (btree t, void (*visit)(poly)); void postOrder (btree t, void (*visit)(poly)); void levelOrder (btree t, void (*visit)(poly)); #endif Implementation // in file “btree.c” #include “btree.h” struct btreeStruct { poly data; btree left; btree right; }; t left data right Operations: “new” // “new” creates an empty new binary tree. Just // as the case for linked list, we may add a head // node. btree newTree () { btree t = (btree)malloc (sizeof (*t)); t->data = NULL; t->left = NULL; t t->right = NULL; return t; } left data right Operations: “new2” // “newTree2” creates an tree node with fields // properly initialized. btree newTree2 (btree left, btree right, poly data) { btree t = (btree)malloc (sizeof (*t)); t->data = data; t->left = left; t t->right = right; return t; } left data right How to build a tree? book chap1 sec11 subsec111 chap2 sec12 sec21 sec22 How to build a tree? A tree can be built in a step-by-step way first new an empty tree t to insert edge (parent, child, ‘l’) or (parent, child, ‘r’), we write a function insert insert (t, parent, child, pos) puts the child node at the pos field of parent node in t if parent does not exist or has already had a pos filed, an error occurs Operations: “insert” // a nearly correct version: btree insert (btree t, poly parent, poly child, char pos) { btree temp = search (t, parent); if (pos == ‘l’) { btree p = new2 (temp->left, NULL, child); temp->left = p; } else {} // similar case for pos == ‘r’ return t; } Operations: “search” btree search (btree t, poly data) { btree p; if (t==NULL) return NULL; else if (t->data == data) // what’s “==“ ? return t; else { p = search (t->left, data); return (p) ? (p) : (search (t->right, data)); } } Client Code Create this tree: book chap1 sec11 subsec111 chap2 sec12 sec21 // the creation process: t = new (); t = insert (t, NULL, book, ‘l’); t = insert (t, book, chap1, ‘l’); t =insert (t, book, chap2, ‘r’); t=insert (t, chap1, sec11, ‘l’); t=insert (t, chap1, sec12, ‘r’); … … sec22 What’s wrong with “insert”? Many subtle conditions: what if the search fail? what if the arguments parent or child be NULL? what if the pos field unequal to ‘l’ or ‘r’? … All these should be checked in real production code a style called defensive programming worth of great recommendation Tree Traversal book Traversal: a systematic way to visit all nodes in a tree. For instance, the visit strategies for the right tree may be: chap1 book, chap1, chap2 or: chap1, book, chap2 and so on. Next, we’ll study four of them, namely: pre-order, inorder, post-order and level-order. chap2 Pre-order Traversal Pre-order: first visit the root node of the tree and then left subtree and finally right subtree Ex: book, chap1, chap2 chap1 book chap2 Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); “a” right left preOrder (t->right, visit); } } “b” right “c” /\ /\ // try visit = printf /\ “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); “a” right left preOrder (t->right, visit); } } “b” right “c” /\ /\ // try visit = printf /\ “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); “a” right left preOrder (t->right, visit); } } “b” right “c” /\ /\ // print out “a” /\ “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); “a” right left preOrder (t->right, visit); } } “b” right “c” /\ /\ // print out “a” /\ “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); “a” right left preOrder (t->right, visit); } } “b” right “c” /\ /\ // print out “a” // print out “b” /\ “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); preOrder (t->right, visit); left “a” right } } // print out “a” // print out “b” // print out “d” /\ “b” right /\ /\ “c” “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); preOrder (t->right, visit); left “a” right } } // print out “a” // print out “b” // print out “d” /\ “b” right /\ /\ “c” “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); preOrder (t->right, visit); left “a” right } } // // // // print print print print out out out out “a” “b” “d” “c” /\ “b” right /\ /\ “c” “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); preOrder (t->right, visit); left “a” right } } // // // // print print print print out out out out “a” “b” “d” “c” /\ “b” right /\ /\ “c” “d” /\ /\ Pre-order Traversal void preOrder (btree t, void (*visit)(poly)) { t if (t) { visit (t->data); preOrder (t->left, visit); preOrder (t->right, visit); left “a” right } } // // // // print print print print out out out out “a” “b” “d” “c” /\ “b” right /\ /\ “c” “d” /\ /\ 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, easyto-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 (btree t, void (*visit)(poly)) { queue q = newQueue (); if (t) enQueue (q, t); while (!queueIsEmpty(q)) { btree temp = deQueue (q); visit (temp->data); if (temp->left) enQueue (q, temp->left); if (temp->right) enQueue (q, temp->right); } return; } Example t left /\ “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t left /\ “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t->l left /\ print out “a” “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t->r t->l left /\ print out “a” “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t->r left /\ print out “a” print out “b” “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t->l->r t->r left /\ print out “a” print out “b” “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t->l->r left /\ print out “a” print out “b” print out “c” “b” right /\ “a” right /\ “c” “d” /\ /\ Example t t->l->r left /\ print out “a” print out “b” print out “c” “b” right /\ “a” right /\ “c” “d” /\ /\ Example t left /\ “b” print out “a” /\ print out “b” print out “c” right print out “d” “a” right /\ “c” “d” /\ /\ Summary Tree is a non-linear data structure every element has 0, 1 or 2 successors structure could be inductively defined Operations could also be inductive defined recursive functions