<<

Trees and Binary Search Trees Dynamic Chapters 18 and 19

! Linked Lists - dynamic , grows and shrinks with data - most operations are linear time (O(N)). CS 3358 ! Can we make a simple that Spring 2015 can do better? Jill Seaman ! Trees - dynamic structure, grows and shrinks with data - most operations are logarithmic time (O(log N)). Sections 18.1-4, 19.1-3

1 2

Tree: : non-recursive definition example

! Tree: of nodes and directed edges - root: one is distinguished as the root - Every node (except root) has exactly exactly one edge coming into it. - Every node can have any number of edges going out of it (zero or more). ! ! Parent: source node of directed edge edges are directed down (source is higher) ! D is the parent of H. Q is a child of J. ! Child: terminal node of directed edge ! Leaf: a node with no children (like H and P)

! 3 Sibling: nodes with same parent (like K,L,M)4 Tree: Example: Expression Trees recursive definition more generally: syntax trees

! Tree: - is empty or - consists of a root node and zero or more nonempty subtrees, with an edge from the root to each subtree.

! leaves are operands

! internal nodes are operators

! 5 can represent entire program as a tree 6

Tree traversal Preorder traversal: Expression Tree

! : operation that converts the values in a tree into a list - Often the list is output ! Pre-order traversal - Print the data from the root node - Do a pre-order traversal on first subtree - Do a pre-order traversal on second subtree . . . ! print node value, process left tree, then right - Do a preorder traversal on last subtree + + a * b * + * d e f g

! This is recursive. What’s the base case? 7 prefix notation (for arithmetic expressions) 8 Postorder traversal: Inorder traversal: Expression Tree Expression Tree

! if each node has 0 to 2 children, you can do inorder traversal ! process left tree, then right, then node ! process left tree, print node value, then process right tree a b c * + d e * f + g * + a + b * c + d * e + f * g ! postfix notation (for arithmetic expressions) 9 ! infix notation (for arithmetic expressions) 10

Binary Trees Binary Trees: implementation

! : a tree in which no node can ! Structure with a data value, and a pointer to the have more than two children. left subtree and another to the right subtree.

struct TreeNode { Object data; // the data TreeNode *left; // left subtree TreeNode *right; // right subtree };

! height: shortest: log2(n) tallest: n

n is the number of ! Like a , but two “next” pointers. nodes in the tree. ! This structure can be used to represent any binary tree. 11 12 Binary Search Trees Binary Search Trees

! A special kind of binary tree

! A data structure used for efficient searching, insertion, and deletion.

! Binary property: For every node X in the tree: - All the values in the left subtree are smaller than the value at X. - All the values in the right subtree are larger than A Not a binary search tree the value at X.

! Not all binary trees are binary search trees 13 14

Binary Search Trees Binary Search Trees

The same set of values may have multiple valid BSTs An inorder traversal of a BST shows the values in sorted order

! Maximum depth of a node: N Inorder traversal: 2 3 4 6 7 9 13 15 17 18 20 ! Average depth of a node: O(log2 N) 15 16 Binary Search Trees: operations BST: find(x)

! insert(x)

! remove(x) (or delete)

! isEmpty() (returns bool) ! makeEmpty() Recursive Algorithm: ! if we are searching for 15 we are done. ! find(x) (returns bool) ! If we are searching for a key < 15, then we ! findMin() (returns ItemType) should search in the left subtree.

! findMax() (returns ItemType) ! If we are searching for a key > 15, then we should search in the right subtree. 17 18

BST: find(x) BST: find(x)

! Pseudocode

Example: search for 9 ! Recursive

! compare 9 to 15, go left bool find (ItemType x, TreeNode ) { if (isEmpty(t)) ! compare 9 to 6, go right Base case return false ! compare 9 to 7 go right if (x < value(t)) return find (x, left(t)) ! compare 9 to 13 go left if (x > value(t)) ! compare 9 to 9: found return find (x, right(t))

return true // x == value(t)

19 } 20 BST: findMin() BST: insert(x)

! Smallest element is found by always taking the left ! Algorithm is similar to find(x) branch. ! If x is found, do nothing (no duplicates in tree) ! Pseudocode ! If x is not found, add a new node with x in place of ! Recursive the last empty subtree that was searched.

! Tree must not be empty Inserting 13: ItemType findMin (TreeNode t) { assert (!isEmpty(t))

if (isEmpty(left(t))) return value(t)

return findMin (left(t))

} 21 22

BST: insert(x) Linked List example:

! x to the end of a singly linked list: ! Pseudocode - Pass the node pointer by reference ! Recursive - Recursive bool insert (ItemType x, TreeNode t) { void List::append (T x) { if (isEmpty(t)) Public function append(x, head); make t’s parent point to new TreeNode(x) }

else if (x < value(t)) void List::append (T x, Node *& p) { insert (x, left(t))

if (p == NULL) { else if (x > value(t)) Private recursive function p = new Node(); insert (x, right(t)) p->data = x; p->next = NULL; //else x == value(t), do nothing, no duplicates } else } 23 append (x, p->next); 24 } BST: remove(x) BST: remove(x)

! Algorithm is starts with finding(x) ! Case 1: Node is a leaf

! If x is not found, do nothing - Can be removed without violating BST property

! ! If x is not found, remove node carefully. Case 2: Node has one child - Must remain a binary search tree (smallers on left, biggers - Make parent pointer bypass the Node and point to child on right).

Does not matter if the child is the left or right child of deleted node 25 26

BST: remove(x) BST: remove(x) removeMin ! Case 3: Node has 2 children - Replace it with the minimum value in the right subtree template - Remove minimum in right: void BST_3358 ::removeMin(TreeNode*& t) { ❖ will be a leaf (case 1), or have only a right subtree (case 2) assert (t); //t must not be empty Note: t is a pointer --cannot have left subtree, or it’s not the minimum passed by reference if (t->left) { removeMin(t->left); } else { TreeNode *temp = t; remove(2): replace it with the t = t->right; //it’s ok if this is null minimum of its right subtree (3) delete temp; and delete that node. } }

27 28 BST: remove(x) Binary Search Trees: deleteItem runtime analyses template void BST_3358 ::deleteItem(TreeNode*& t, const ItemType& newItem) ! Cost of each operation is proportional to the { if (t == NULL) return; // not found Note: t is a pointer number of nodes accessed passed by reference else if (newItem < t->data) // search left deleteItem(t->left, newItem); ! depth of the node (height of the tree) else if (newItem > t->data) // search right deleteItem(t->right, newItem); ! best case: O(log N) (balanced tree) else { // newItem == t->data: remove t if (t->left && t->right) { // two children ! worst case: O(N) (tree is a list) t->data = findMin(t->right); removeMin(t->right); } else { // one or zero children: skip over t ! average case: ?? TreeNode *temp = t; if (t->left) t = t->left; - Theorem: on average, the depth of a binary search else tree node, assuming random insertion sequences, t = t->right; //ok if this is null delete temp; is 1.38 log N } } } 29 30