Dr. Na Li CSE @ UTA April 16, 2013 Trees are graphical representations of hierarchies. For example, organization charts The expression 2 + 3 - 4 could be represented as either of these trees: In this course we will only discuss trees in which each node has at most two children: binary trees. The top node is called the root and the nodes at the end of a path without child nodes are the leaves. In order for us to navigate our list, we must keep track of the address of each piece of allocated memory. We do this by creating a structure that contains a variable for storing our data as well as pointer variables for storing the address of the child nodes. In the simplest case, a node in the binary tree will have this form: ◦ ◦ ◦ ◦ ◦ ◦ struct node { int value; /* or any other type */ struct node* left; struct node* right; }; In order to move through the tree such that each node is visited exactly once, we have two basic options: ◦ breadth-first traversal – left-to-right (or right-toleft), one level at a time ◦ depth-first traversal – as deep as possible on the left (or right), before moving to the right (or left) Visiting a tree level by level An animation is available here. http://upload.wikimedia.org/wikipedia/com mons/4/46/Animated_BFS.gif procedure BFS(root in T): create a queue Q enqueue root onto Q while Q is not empty: t ← Q.dequeue() enqueue t.leftchild onto Q enqueue t.rightchild onto Q Can you implement Breadth-first traversal? Depth-first traversal has several options: ◦ preorder traversal ◦ inorder traversal ◦ postorder traversal Preorder using the recursive process: if node != NULL use current node follow left child follow right child Inorder using the recursive process: ◦ ◦ ◦ ◦ if node != NULL follow left child use current node follow right child Postorder using the recursive process: ◦ ◦ ◦ ◦ if node != NULL follow left child follow right child use current node Depth-first ◦ Preorder traversal sequence: F, B, A, D, C, E, G, I, H (root, left, right) ◦ Inorder traversal sequence: A, B, C, D, E, F, G, H, I (left, root, right) Breadth-firstLevel-order traversal sequence: F, B, G, A, D, I, C, E, H Can you implement Depth-first traversal? http://cslibrary.stanford.edu/110/BinaryTree s.html Data Structures and Algorithms: Annotated Reference with Examples from Barnett and Del Tongo (a free e-book) ◦ http://dotnetslackers.com/projects/Data-Structures-AndAlgorithms/ C data structures from cprogramminglanguage.net ◦ http://cprogramminglanguage.net/c-datastructure.aspx ◦ The properties of a BST First, it’s a binary tree. ◦ Each node has at most two child nodes Second, it supports the searching function. ◦ The order comes from the fact that the data in the left child of a node precedes the data in the node which also precedes the data in the right child. ◦ Each node keeps this property. Suppose all data are unique, no redundant values int AddItem(Item pi, Tree * ptree) { Node * new_node; new_node = MakeNode(pi); if(new_node == NULL) { printf("Couldn't create a new node.\n"); return 0; } ptree->size++; if(ptree->root == NULL) ptree->root = new_node; else AddNode(new_node, ptree->root); return 1; } void AddNode(Node * new_node, Node * root) { if(new_node->item < root->item) { if(root->left == NULL) root->left = new_node; else AddNode(new_node, root->left); } else { if(root->right == NULL) root->right = new_node; else AddNode(new_node, root->right); } } int main(void) { Item itarr[10] = {12,3,43,22,45,67,78,83,88,98}; Tree tr; int i; InitializeTree(&tr); /*Create a BST*/ for(i = 0; i< 10; i++) { AddItem(itarr[i], &tr); printf("The tree after inserting the %d node: ", i); InOrderTraverseTree(tr.root); printf("\n"); } } How many approaches to traverse a BST? Which one can give us a sequence of sorted integers? void InOrderTraverseTree(Node * root) { if(root != NULL) { InOrderTraverseTree(root->left); printf("%d ", root->item); InOrderTraverseTree(root->right); } } The node to be deleted has only one subtree ◦ The left child of the node is NULL. ◦ The right child of the node is NULL. ◦ To delete N, we need to connect the parent of N directly to N's only subtree. The node to be deleted has two subtrees ◦ Neither of child nodes is NULL. ◦ We want to delete with minimum amount of work and disruption to the structure of the tree ◦ To delete N, we need to connect N’s right child with the largest value from N’s left subtree and then replace N with its left child. int DeleteItem(Item pi, Tree * ptree) { Pair look; look = SeekItem(pi, ptree); if(look.child == NULL) return 0; if(look.parent == NULL) DeleteNode(&ptree->root); else if(look.parent->left == look.child) DeleteNode(&look.parent->left); else DeleteNode(&look.parent->right); ptree->size--; } return 1; void DeleteNode(Node ** ptr) // ptr is address of parent member pointing to target node // * ptr is the address of the target node { Node * temp; printf("The item to be deleted is %d.\n",(*ptr)->item); if((*ptr)->left == NULL) { temp = * ptr; *ptr = (*ptr)->right; free(temp); } else if((*ptr)->right == NULL) { temp = * ptr; *ptr = (*ptr)->left; free(temp); } else { for(temp = (*ptr)->left; temp->right != NULL; temp = temp->right) continue; temp->right = (*ptr)->right; temp = *ptr; *ptr=(*ptr)->left; free(temp); } } Pair SeekItem(Item pi, Tree * ptree) { Pair look; look.parent = NULL; look.child = ptree->root; if(look.child == NULL) return look; while(look.child != NULL) { if(pi < look.child->item) { look.parent = look.child; look.child = look.child->left; } else if (pi > look.child->item) { look.parent = look.child; look.child = look.child->right; } else break; } return look; } int InTree(Item pi, Tree * ptree) { return (SeekItem(pi, ptree).child == NULL)?0:1; } Can you implement it using a recursive function? http://cslibrary.stanford.edu/110/BinaryTree s.html http://webdocs.cs.ualberta.ca/~holte/T26/de l-from-bst.html