CS 261: Data Structures
Binary Tree Traversals Binary Search Trees
1 Binary Tree Traversals • How to examine nodes in a tree? • A list is a simpler structure: – can be traversed either forward or backward
• What order do we visit nodes in a tree?
• Most common tree traversal orders: –Pre-order –In-order –Post-order
2 Binary Tree Traversals • All traversal algorithms have to: – Process node – Process left subtree – Process right subtree
Traversal order is determined by the order these operations are done
3 Binary Tree Traversals – Most Common
1.Node, left, right à Pre-order 2.Left, node, right à In-order 3.Left, right, node à Post-order
4 Pre-Order Binary Tree Traversal
• Process order à Node, Left subtree, Right subtree
p void preorder(struct Node *node) { if (node != 0){ process (node->val); s e preorder(node->left); preorder(node->rght); } a m l r } a t e
Example result: p s a m a e l r t e e e
5 Post-Order Binary Tree Traversal
• Process order à Left subtree, Right subtree, Node
p void postorder(struct Node *node) { if (node != 0){ s e postorder(node->left); postorder(node->rght); process(node->val); a m l r } } a t e
Example result: a a m s l t e e r e p e
6 In-Order Binary Tree Traversal
• Process order à Left subtree, Node, Right subtree
p void inorder(struct Node *node) { if (node != 0){ inorder(node->left); s e process(node->val); inorder(node->rght); a m l r } } a t e
Example result: a s a m p l e t r e e e
7 Complexity of Binary Tree Traversals • Each traversal requires constant work at each node (not including recursive calls) • Order not important • Iterating over all n elements in a tree requires O(n) time
8 Binary Search Trees
9 Binary Search Tree • = Binary trees where every node value is: –Greater than all its left descendants –Less than or equal to all its right descendants –In-order traversal returns elements in sorted order
• If tree is reasonably full (well balanced), searching for an element is O(log n)
10 Binary Search Tree: Example
Alex
Abner Angela
Abigail Adela Alice Audrey
Adam Agnes Allen Arthur
11 A Node in BST
struct Node { TYPE val; struct Node *left; /* Left child */ struct Node *right; /* Right child */ };
12 Binary Search Tree (BST): Implementation
struct BST { struct Node *root;
int size;
};
void initBST(struct BST *tree); int containsBST(struct BST *tree, TYPE val);
void addBST(struct BST *tree, TYPE val);
void removeBST(struct BST *tree, TYPE val);
int sizeBST(struct BST *tree);
13 Sorted Bag Implementation: Contains • Start at root • At each node, compare value to node value: –Return true if match –If value is less than node value, go to left child (and repeat) –If value is greater than node value, go to right child (and repeat) –If node is null, return false
14 Bag Implementation: Contains • Traverses a path from the root to the leaf • Therefore, if tree is reasonably full, execution time is O( ?? )
15 BST: Contains/Find Example
Alex Object to find Agnes
Abner Angela
Abigail Adela Alice Audrey
Adam Agnes Allen Arthur
16 BST: Add Example
Alex Object to add Aaron
Abner Angela
Abigail Adela Alice Audrey
Aaron Adam Agnes Allen Arthur
“Aaron” should be added here
17 Add: Calls a Utility Routine
void addBST(struct BST *tree, TYPE val) {
assert(tree);
tree->root = _addNode(tree->root, val);
tree->size++;
}
What is the complexity? O( ?? )
18 Useful Auxiliary Function -- Recursion struct Node * _addNode(struct Node * current, TYPE val){ if (current == 0) {/* always first check when to stop */
. . . /*make a new node and return the pointer to it*/ } else { /* call recursion left or right */ } return current; } return the same pointer
19 Useful Auxiliary Function -- Recursion struct Node * _addNode(struct Node * current, TYPE val){ if (current == 0){ . . . /*make a new node and return the pointer to it*/ }else{ if (val < current->val) /* recursion left */ current->left = _addNode(current->left, val); else /* recursion right */ current->right = _addNode(current->right, val); } return current; }
20 Useful Auxiliary Function struct Node * _addNode(struct Node * current, TYPE val){ if (current == 0){ struct Node * new = (struct Node *) malloc(sizeof(struct Node)); assert(new != 0); new->value = val; new->left = new->right = 0; return new; }else if (val < current->val) current->left = _addNode(current->left, val); else current->right = _addNode(current->right, val); return current; } 21 BST: Remove
Alex
Abner Angela
Abigail Adela Alice Audrey
Adam Agnes Allen Arthur
How would you remove: Audrey? Angela?
22 Who Fills the Hole in BST?
• Answer: the leftmost descendant of the right child = smallest element in the right subtree • Try this on a few values
23 BST: Remove Example
Element to Alex remove
Replace with: Abner leftmost right Angela
Abigail Adela Alice Audrey
Adam Agnes Allen Arthur
24 BST: Remove Example
Alex
Abner Arthur
Abigail Adela Alice Audrey
Adam Agnes Allen
After call to remove 25 Special Case • What if you don’t have the right child?
• Try removing “Audrey” –Simply, return the left child Angela
Alice Audrey
Allen Arthur
26 Remove
void removeBST (struct BST *tree, TYPE e) {
if (containsBST(tree, e)) {
tree->root = _removeNode(tree->root, e);
tree->size--;
}
}
27 Remove Node
struct Node *_removeNode(struct Node *current, TYPE e){
if (current->val == e)
/* Found it, remove it */
else
/* not found, so recursive call */
}
28 Remove Node struct Node *_removeNode(struct Node *current, TYPE e){ struct Node *node; assert(current); if (current->val == e) /* Found it, remove it */ if (current->right == NULL){ node = current->left; free(current); return node; /* returns the left child */ } else /* replace current->val with the value of the leftmost descendant of the right child */ current->val = _leftMost(current->right); current->right = _removeLeftmost(current->right); else /* not found, so recursive call */ ... }
29 Remove Node struct Node *_removeNode(struct Node *current, TYPE e){ if (current->val == e) /* Found it, remove it */ ... else /* not found, so recursive call */ if( e < current->val) current->left = _removeNode(current->left, e); else current->right = _removeNode(current->right, e);
return current; }
30 Useful Routines: _leftMost
/*Returns value of leftmost child of current node*/
TYPE _leftMost(struct Node *current) {
while(current->left != 0)
current = current->left;
return current->val;
}
31 Useful Routines: _removeLeftmost
/* Removes the leftmost descendant of current */ struct Node *_removeLeftmost(struct Node *current) { struct Node *temp; if(current->left != 0){ current->left = _removeLeftmost(current->left); return current; } temp = current->right; free(current); return temp; } 32 Complexity • Running down a path from root to leaf
• What is the time complexity? O( ?? )
33