1 / 34

Turgay Korkmaz Office : NPB 3.330 Phone: (210) 458-7346 Fax: (210) 458-4437

Do Quiz15. CS 2123 Data Structures Ch 13 – Trees Basic definitions and Binary Search Tree (BST). Turgay Korkmaz Office : NPB 3.330 Phone: (210) 458-7346 Fax: (210) 458-4437 e-mail: korkmaz@cs.utsa.edu web: www.cs.utsa.edu/~korkmaz.

npleasants
Download Presentation

Turgay Korkmaz Office : NPB 3.330 Phone: (210) 458-7346 Fax: (210) 458-4437

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Do Quiz15 CS 2123 Data Structures Ch 13 – Trees Basic definitions and Binary Search Tree (BST) Turgay Korkmaz Office: NPB 3.330 Phone: (210) 458-7346 Fax: (210) 458-4437 e-mail: korkmaz@cs.utsa.edu web: www.cs.utsa.edu/~korkmaz Thanks to Eric S. Roberts, the author of our textbook, for providing some slides/figures/programs.

  2. Objectives • To understand the concept of trees and the standard terminology used to describe them. • To appreciate the recursive nature of a tree and how that recursive structure is reflected in its underlying representation. • To become familiar with the data structures and algorithms used to implement binary search trees. • To recognize that it is possible to maintain balance in a binary search tree as new keys are inserted. (Part 2) • To learn how binary search trees can be implemented as a general abstraction.

  3. What is a tree? • A tree is defined to be a collection of individual entries called nodes for which the following properties hold: • As long as the tree contains any nodes at all, there is a specific node called the root that forms the top of a hierarchy. • Every other node is connected to the root by a unique line of descent.

  4. Trees Are Everywhere • Tree-structured hierarchies occur in many contexts outside of computer science. • Game trees • Biological classifications • Organization charts • Directory hierarchies • Family trees • Many more…

  5. Tree Terminology • Most terms come from family tree analogue • William I is the root of the tree. • Adela is a child of William I and the parent of Stephen. • Robert, William II, Adela, and Henry I are siblings. • Henry II is a descendant of William I, Henry I, and Matilda • William I is an ancestor of everyone else. • Other terms • Nodes that have no children are called leaves • Nodes that are neither the root nor a leaf are called interiornodes • The height/depth of a tree is the length of the longest path from root to a leaf • vs. level

  6. Recursive nature of a tree • Take any node in a tree together with all its descendants, the result is also a tree (called a subtree of the original one) • Each node in a tree can be considered the root of its own subtree • This is the recursive nature of tree structures. • A tree is simply a node and a set of attached subtrees — possibly empty set in the case of a leaf node— • The recursive character of trees is fundamental to their underlying representation as well as to most algorithms that operate on trees.

  7. Representing family trees in C • How can we represent the hierarchical (parent/children) relationships among the nodes • Include a pointer in the parent to point each child • A tree is a pointer to a node. • A node is a structure that contains some number of trees. Use index values of an array (Heap) #define MaxChildren 5 typedef struct familyNode { char *name; struct familyNode *children[MaxChildren]; } familyNodeT; typedef familyNodeT *familyTreeT; typedef struct familyNode { char *name; struct familyNode *children0, *children1, *children2, …; } familyNodeT; typedef familyNodeT *familyTreeT;

  8. data Binary Trees:One of the most important subclasses of trees with many practical applications left right • A binary tree is defined to be a tree in which the following additional properties hold: • Each node in the tree has at most two children. • Every node except the root is designated as either a left child or a right child of its parent. • This geometrical relationship allows to represent ordered collections of data using binary trees (binary search tree)

  9. Binary Search Trees < < • A binary search tree is defined by the following properties: • Every node contains—possibly in addition to other data—a special value called a keythat defines the order of the nodes. • Key values are unique, in the sense that no key can appear more than once in the tree. • At every node in the tree, the key value must be • greater than all the keys in its left subtree • less than all the keys in its right subtree. D G B E C A F

  10. Motivation for UsingBinary Search Trees (BST) • Suppose we want to keep keys sorted • What will be the complexity of lookup and insert if we use an Array • Lookup can be done in O(log N), how? • Enter/Insert will be in O(N) • How about using Linked List (LL) • Lookup/Enter will be done in O(N). Why? • LL cannot find middle element efficiently (skip list may help) • Can both Lookup and Enter be done in O(log N)? • Yes, by using Binary Search Trees (BST)

  11. Finding nodes in a binary search tree: Recursive nodeT *FindNode(nodeT *t, char key) { if (t == NULL) return NULL; if (key == t->key) return t; if (key < t->key) { return FindNode(t->left, key); } else { return FindNode(t->right, key); } } typedefstructnodeT { char key; structnodeT *left, *right; } nodeT, *treeT; D G B E C A t F nodeT *node; nodeT *t; … node=FindNode(t, ‘C’); !!! Note !!!: Textbook uses treeT. Instead, I use nodeT * Is there any difference? Depending on key type We may use a different function to compare keys

  12. Exercise: Iterative version of Finding nodes in a binary search tree nodeT *FindNode(nodeT *t, char key) { while(t !=NULL) { if (key == t->key) return t; if (key < t->key) { t = t->left; } else { t = t->right; } } return NULL; } typedef struct nodeT { char key; struct nodeT *left, *right; } nodeT, *treeT; D G B E C A t F nodeT *node; nodeT *t; … node=FindNode(t, ‘C’);

  13. Tree Traversal (inorder) void DisplayTree(nodeT *t) { if (t != NULL) { DisplayTree(t->left); printf(“%c “, t->key); DisplayTree(t->right); } } D G B E C A t nodeT *node; nodeT *t; … DisplayTree(t); F A B C DE F G

  14. Preorder and Postorder Tree Traversal void PreOrderWalk(nodeT *t) { if (t != NULL) { printf(“%c “, t->key); PreOrderWalk(t->left); PreOrderWalk(t->right); } } void PostOrderWalk(nodeT *t) { if (t != NULL) { PostOrderWalk(t->left); PostOrderWalk(t->right); printf(“%c “, t->key); } } D G B E C A t F D B A C G E F A C B F E G D

  15. Exercise: what will be the output void DisplayTree(nodeT *t) { if (t != NULL) { DisplayTree(t->left); printf(“%c “, t->key); DisplayTree(t->right); } } void DisplayTree2(nodeT *t) { if (t != NULL) { • DisplayTree(t->right); printf(“%c “, t->key); • DisplayTree(t->left); } } D G B E C A t F _ _ _ D_ _ _ A B C DE F G

  16. Exercise:How about outputs if we switch the recersive call lines void PreOrderWalk(nodeT *t) { if (t != NULL) { printf(“%c “, t->key); PreOrderWalk(t->left); PreOrderWalk(t->right); } } void PostOrderWalk(nodeT *t) { if (t != NULL) { PostOrderWalk(t->left); PostOrderWalk(t->right); printf(“%c “, t->key); } } D G B E C A t F D B A C G E F A C B F E G D D _ _ __ _ _ _ _ __ _ _ D • PreOrderWalk(t->right); • PreOrderWalk(t->left); • PostOrderWalk(t->right); • PostOrderWalk(t->left);

  17. Exercise: Modify one of the traversal functions to print the tree as follow void PrintTree(nodeT *t) { ModifyPreOrderWalk(t, 1); } void ModifyPreOrderWalk(nodeT *t, int h) { int i; if (t == NULL) return; printf(“%c\n“, t->key); ModifyPreOrderWalk(t->left, h+1); ModifyPreOrderWalk(t->right, h+1); } } D +---B | +---A | +---C +---G | +---E | | +---F D G B E C A for(i=0; i < h-1; i++) { printf(“| “); } if (h>1) printf(“+---“); t F

  18. Exercise: Height typedefstructnodeT { char key; structnodeT *left, *right; } nodeT, *treeT; • Suppose we want to find the height of a Binary Search Tree t • Write a function that returns the height of the tree • Recursive Idea 1 + Maximum of (height of left subtree, height of right subtree). int height(nodeT *t) { if (t == NULL) return 0; else return (1 + maximumof( height(t->left), height(t->right)) ); }

  19. Exercise: Sum, Min, Max struct tree_node { int data; struct tree_node *left, *right; } • Suppose we store integer values in a Binary Search Tree t • Write a function that returns the sum of values in the tree • Recursive Idea • Value of the current node • +the sum of values of all nodes of left subtree • + the sum of values of all nodes in right subtree. • How about max, min in bst or just in a binary tree where values may not be sorted? int sum(structtree_node *p) { if (p == NULL) return 0; else return (p->data + sum(p->left) + sum(p->right) ); }

  20. Exercise: Tree Traversal level order void DisplayTreeLevelOrder(nodeT *t) { if (t != NULL) { ?????? } } D G B E C nodeT *node; nodeT *t; … DisplayTreeLevelOrder(t); A t F D B G A C E F • A little bit harder version • D • B G • A C E • F

  21. /* queue.h */ #ifndef _queue_h #define _queue_h • #define New(ptr_t) ((ptr_t)malloc(sizeof *((ptr_t) NULL))) • typedefintbool; typedefvoid *queueElementT; //int,char typedefstructqueueCDT *queueADT; queueADTNewQueue(void); void FreeQueue(queueADT queue); void Enqueue(queueADT queue, queueElementT element); queueElementTDequeue(queueADT queue); boolQueueIsEmpty(queueADT queue); boolQueueIsFull(queueADT queue); intQueueLength(queueADT queue); queueElementTGetQueueElement(queueADT queue, int index); #endif typedefstructnodeT { char key; structnodeT *left, *right; } nodeT, *treeT; D G B • void DisplayTreeLevelOrder(nodeT *t) { • nodeT *node; queueADTmyQ; myQ = NewQueue(); • Enqueue(myQ, t); • while(!QueueIsEmpty(myQ)){ • node = Dequeue(myQ)); • if(!node) { • printf("%c ", node->key); • Enqueue( myQ, node->left); • Enqueue( myQ, node->right); • } • } • FreeQueue(myQ); • } E C A t F D B G A C E F

  22. Insert - Delete

  23. typedefstructnodeT { char key; structnodeT *left, *right; } nodeT, *treeT; Creating a tree in a client program main() { nodeT nt1, *nt2; treeT tt1, *tt2; nt2 = (nodeT *) malloc(sizeof(nodeT)); if(nt2==NULL) { printf(”no memory”); exit(-1); } nt1.key = ‘A’; nt1.left = nt1.right= NULL; nt2->key = ‘D’; nt2->left = nt2->right= NULL; tt1 = nt2; tt2 = &nt2; InsertNode(&nt2, ‘B’); // InsertNode(tt2, ‘B’); } nt1 nt2 // nodeT *tt1, **tt2 tt1 // nt2 = New(nodeT *) ; tt2 void InsertNode(nodeT **tptr, char key) B

  24. Inserting new nodes in a binary search tree void InsertNode(nodeT **tptr, char key) { nodeT *t, *tmp; t=*tptr; if (t == NULL) { tmp=New(nodeT *); // malloc(????); if NULL tmp->key = key; tmp->left=tmp->right=NULL; *tptr=tmp; return; } if (key < t->key) { InsertNode(&t->left, key); } else { InsertNode(&t->right, key); } } typedef struct nodeT { char key; struct nodeT *left, *right; } nodeT, *treeT; D t G B C nodeT *node; nodeT *t=NULL; InsertNode(&t, ‘D’); InsertNode(&t, ‘B’); InsertNode(&t, ‘G); InsertNode(&t, ‘C’); … void InsertNode(nodeT **tptr, char key) { if (*tptr == NULL) { *tptr=New(treeT); (*tptr)->key = key; (*tptr)->left=(*tptr)->right=NULL; return; } if (key < (*tptr)->key) { InsertNode(&(*tptr)->left, key); } else { InsertNode(&(*tptr)->right, key); } }

  25. Exercise: modify this such that we can return the depth of the inserted node void InsertNode(nodeT **tptr, char key) { nodeT *t, *tmp; t=*tptr; if (t == NULL) { tmp=New(nodeT *); tmp->key = key; tmp->left=tmp->right=NULL; *tptr=tmp; return; } if (key < t->key) { InsertNode(&t->left, key); } else { InsertNode(&t->right, key); } } typedefstructnodeT { char key; structnodeT *parent; structnodeT *left, *right; } nodeT, *treeT;

  26. Exercise: modify this such that each node points parent node void InsertNode(nodeT **tptr, char key) { nodeT *t, *tmp; t=*tptr; if (t == NULL) { tmp=New(nodeT *); tmp->key = key; tmp->left=tmp->right=NULL; *tptr=tmp; return; } if (key < t->key) { InsertNode(&t->left, key); } else { InsertNode(&t->right, key); } } typedefstructnodeT { char key; structnodeT *parent; structnodeT *left, *right; } nodeT, *treeT;

  27. Deleting nodes from a binary search tree

  28. Deleting nodes from a binary search tree D D D D D D D G G G G G G E B B B B B B B E E E E E F C C C C C C C F A A A A A A Delete A Delete E Delete G Delete B or D ??? F F F F F target->left==NULL && target->right==NULL target->left == NULL target->right == NULL

  29. Deleting nodes from a binary search tree: easy cases void DeleteNode(nodeT **p) { nodeT *target; target=*p; if (target->left==NULL && target->right==NULL) { *p=NULL; } else if (target->left == NULL) { *p=target->right; } else if (target->right == NULL) { *p=target->left; } else { /* target has two children, see next slide */ } free(target); } typedefstructnodeT { char key; structnodeT *left, *right; } nodeT, *treeT; D D G G B B E C C F A A left t F right nodeT *t; // Suppose we want to delete ‘E’, // find/determine pointer to target node DeleteNode(&t->right->left); // if ‘A’, DeleteNode(&t->left->left);

  30. Deleting nodes from a binary search tree: two children (incomplete) void DeleteNode(nodeT **p) { nodeT *target, *lmd_r, *plmd_r; target=*p; … /* easy cases, see previous slide */ } else { plmd_r = target; lmd_r = target->right; while( lmd_r->left != NULL){ plmd_r = lmd_r; lmd_r = lmd_r->left; } plmd_r->left = lmd_r->right; lmd_r->left = target->left; lmd_r->right = target->right; *p = lmd_r; } free(target); } E D G G B B DeleteNode(&t); Replace the target node with its immediate successor, which is the smallest value in the right subtree (lmd_r -- leftmost descendant in right subtree) Delete lmd_r (easy case, why?) F E C C A A t t F target->key = lmd_r->key; target = lmd_r; Is there any other case missing!

  31. Deleting nodes from a binary search tree: two children (corrected) void DeleteNode(nodeT **p) { nodeT *target, *lmd_r, *plmd_r; target=*p; … /* easy cases, see previous slide */ } else { plmd_r = target; lmd_r = target->right; while( lmd_r->left != NULL){ plmd_r = lmd_r; lmd_r = lmd_r->left; } if(plmd_r == target) plmd_r->right = lmd_r->right; else plmd_r->left = lmd_r->right; lmd_r->left = target->left; lmd_r->right = target->right; *p = lmd_r; } free(target); } G D Z G B C DeleteNode(&t); Z Replace the target node with its immediate successor, which is the smallest value in the right subtree (lmd_r -- leftmost descendant in right subtree) Delete lmd_r (easy case, why?) C C A A t t target->key = lmd_r->key; target = lmd_r; Can you think of another strategy (see the exercise in the next slide)

  32. Exercise: new strategy for deleting nodes from a binary search tree: two children void DeleteNode(nodeT **p) /* Modify this one*/ { nodeT *target, *lmd_r, *plmd_r; target=*p; // *rmd_l, *prmd_l; … /* easy cases see previous slide */ } else { plmd_r = target; lmd_r = target->right; while( lmd_r->left != NULL){ plmd_r = lmd_r; lmd_r = lmd_r->left; } if(plmd_r == target) plmd_r->right = lmd_r->right; else plmd_r->left = lmd_r->right; lmd_r->left = target->left; lmd_r->right = target->right; *p = lmd_r; } free(target); } Delete D C D G G B B Replace the target node with its immediate predecessor, which is the largest value in the left subtree (rmd_l -- rightmost descendant in left subtree) Delete rmd_l (easy case, why?) E E C A A F F target->key = lmd_r->key; target = lmd_r;

  33. Exercise: given this, write another function that creates a new copy of the given tree. void InsertNode(nodeT **tptr, char key) { nodeT *t, *tmp; t=*tptr; if (t == NULL) { tmp=New(nodeT *); tmp->key = key; tmp->left=tmp->right=NULL; *tptr=tmp; return; } if (key < t->key) { InsertNode(&t->left, key); } else { InsertNode(&t->right, key); } } typedefstructnodeT { char key; structnodeT *parent; structnodeT *left, *right; } nodeT, *treeT; nodeT *t, *cpyt; // …. t is created … cpyt = CopyTree(t);

  34. Final word: Importance of Recursion in Binary Trees • It's very difficult to think about how to iteratively go through all the nodes in a binary tree unless you think recursively??? • With recursion, the code is reasonably concise and simple. • But in some cases iterative approaches might be possible and more efficient

More Related