Week 08
Recursion | 1/42 |
A recursive function is one that calls itself within the program text
int factorial(int n) {// recursive version int retval; if (n == 0) { retval = 1; } else { retval = n * factorial(n-1); } return retval;
Mathematical definitions often lend themselves directly to a recursive implementation.
... Recursion | 2/42 |
Exercise
Use a recursive function to implement Euclid's algorithm for computing the greatest common divisor
gcd(651,378) = gcd(273,378) = gcd(273,105) = gcd(168,105) = gcd(63,105) = gcd(63,42) = gcd(21,42) = gcd(21,21) = 21
... Recursion | 3/42 |
Most list functions can be implemented recursively
->next
int length(List L) {// recusive version int retval; if (L == NULL) {// base case retval = 0; } else {// recursive case retval = length(L->next) + 1; } return retval; }
... Recursion | 4/42 |
// Search for item in sorted int list // Returns pointer to node, or NULL if not found Node *search(SortedIntList L, int v) { Node *retval; if (L == NULL) { retval = NULL; } else if (v < L->value) {// v can't be in the list retval = NULL; } else if (v > L->value) {// recursive case retval = search(L->next, v); } else {// found retval = L; } return retval; }
Exercise Write recursive functions to insert/delete a list element
Node *insert(SortedIntList, int); Node *delete(SortedIntList, int);
Data Structures | 5/42 |
Structured data objects
struct
... Data Structures | 6/42 |
Typical operations on a data structure
... Data Structures | 7/42 |
Data structures we have seen so far:
... Data Structures | 8/42 |
Implementing Complex Structures | 9/42 |
So far, we have looked at linear structures:
typedef struct node { ValueType value; struct node *next;// might also have *prev } Node; typedef Node *List;
One implementation of complex structures generalises this:
typedef struct node { ValueType value; struct node *neighbours[]; } Node; typedef Node *Collection;
Binary Search Trees |
Binary Trees | 11/42 |
Binary trees are a type of dynamic data structure
Cost for list with 1000 nodes ... linear: 1000, binary tree: 10
... Binary Trees | 12/42 |
Trees are branched dynamic data structures
... Binary Trees | 13/42 |
Trees can be viewed as a set of nested structures:
... Binary Trees | 14/42 |
Node level = path length from root to node
Tree height = max path length from root to leaf
Height of tree with n nodes: min = log2n , max = n-1
... Binary Trees | 15/42 |
Trees are used in many contexts, e.g.
... Binary Trees | 16/42 |
Search trees have the properties
... Binary Trees | 17/42 |
Examples of binary search trees:
Shape of tree is determined by order of insertion.
Exercise: Binary Search Trees | 18/42 |
For each of the following sequences of values:
Representation of Binary Trees | 19/42 |
Binary trees consist of Node
Node
int
typedef struct node { int value; struct node *left; struct node *right; } Node; typedef Node *Tree;
A tree is represented by a pointer to its root node.
Operations on Binary Trees | 20/42 |
For the rest of our discussion, we consider binary search trees.
A binary search tree type would typically have operations:
// make an empty tree Tree emptyTree();// insert a new value into the tree Tree insert(Tree t, int v);// delete a value from the tree Tree delete(Tree t, int v);// search for a value Node *search(Tree t, int v);
... Operations on Binary Trees | 21/42 |
A useful auxiliary operation:
// Make a new Node Node *newNode(int v) { Node *new; new = (Node *)malloc(sizeof(Node)); assert(new != NULL); new->value = v; new->left = NULL; new->right = NULL; return new; }
After creating such a Node
Tree
Searching in Search Trees | 22/42 |
Most tree algorithms are best described recursively
Example animation
// Search for item in tree // Returns pointer to node, or NULL if not found Node *search(Tree t, int v) { Node *retval; if (t == NULL) { retval = NULL; } else if (v < t->value) { retval = search(t->left, v); } else if (v > t->value) { retval = search(t->right, v); } else {// found retval = t; } return retval; }
Exercise: Count Nodes in a Binary Tree | 23/42 |
Implement a function int size(Tree t)
Insertion into Search Trees | 24/42 |
// Recursive version // Insert into appropriate subtree Tree insert(Tree t, int v) { if (t == NULL) t = newNode(v); else if (v == t->value) { ;// no duplicates allowed } else if (v < t->value) { t->left = insert(t->left, v); } else if (v > t->value) { t->right = insert(t->right, v); } return t; }
... Insertion into Search Trees | 25/42 |
// Non-recursive version // Find location in tree; attach new leaf void insert(Tree *t, int v) { char lastTurn; Node *curr = *t; Node *parent = NULL;// empty tree; special case if (curr == NULL) { *t = newNode(v); } else {// find where new leaf belongs while (curr != NULL) { if (v == curr->value) { ;// no duplicates allowed } else if (v < curr->value) { parent = curr; curr = curr->left; lastTurn = 'L'; } else if (v > curr->value) { parent = curr; curr = curr->right; lastTurn = 'R'; } }// connect new node switch (lastTurn) { case 'L': parent->left = newNode(v); break; case 'R': parent->right = newNode(v); break; } } }
Tree Traversal | 26/42 |
For many traversals/iterations
... Tree Traversal | 27/42 |
Consider visiting an expression tree like:
NLR: + * 1 3 - * 5 7 9 (useful for building tree)
LNR: 1 * 3 + 5 * 7 - 9 ("natural" order)
LRN: 1 3 * 5 7 * 9 - + (useful for evaluation)
... Tree Traversal | 28/42 |
Inorder traversal:
void TraverseLNR(Tree t) { if (t != NULL) { TraverseLNR(t->left); VISIT(t->value); TraverseLNR(t->right); } }
where VISIT
Node
Exercise: Tree Traversal | 29/42 |
Show NLR, LNR, LRN traversals for the following tree:
Tree Traversal | 30/42 |
Traversal is a generic operation:
Inorder traversal (with run-time choice of visit operation):
void TraverseLNR(Tree t, void (*visit)(int)) { if (t != NULL) { TraverseLNR(t->left, visit); (*visit)(t->value); TraverseLNR(t->right, visit); } }
... Tree Traversal | 31/42 |
Consider how we might use the above TraverseLNR()
void show(int v) { printf("%d ",v); }// ... which might be used as Tree t; ... TraverseLNR(t, show);
The second parameter has type pointer to function.
Deletion from BSTs |
Deletion from Binary Search Trees | 33/42 |
Insertion into a binary search tree is easy:
... Deletion from Binary Search Trees | 34/42 |
Case 1: value to be deleted is a leaf (zero subtrees)
... Deletion from Binary Search Trees | 35/42 |
Case 1: value to be deleted is a leaf (zero subtrees)
... Deletion from Binary Search Trees | 36/42 |
Case 2: value to be deleted has one subtree
... Deletion from Binary Search Trees | 37/42 |
Case 2: value to be deleted has one subtree
... Deletion from Binary Search Trees | 38/42 |
Case 3: value to be deleted has two subtrees
Replace deleted node by its immediate successor
... Deletion from Binary Search Trees | 39/42 |
Case 3: value to be deleted has two subtrees
... Deletion from Binary Search Trees | 40/42 |
Tree delete(Tree t, int v){ if (t == NULL) { ;// v not found, nothing to do } else if (v < t->value) {// delete v in left subtree t->left = delete(t->left, v); } else if (v > t->value) {// delete v in right subtree t->right = delete(t->right, v); } else {// v == t->value, so the node 't' must be deleted // code below violates style, just to make logic clear Tree n;// temporary if (t->left==NULL && t->right==NULL) n=NULL;// 0 children else if (t->left ==NULL) n=t->right;// 1 child else if (t->right==NULL) n=t->left;// 1 child else n=joinAtMinimum(t->left,t->right); free(t); t = n; } return t; }
... Deletion from Binary Search Trees | 41/42 |
// Joins t1 and t2 with the minimum of t2 as new root Tree joinAtMinimum(Tree t1, Tree t2){ Tree nuroot = t2; Tree p = NULL; while (nuroot->left != NULL) { p = nuroot; nuroot = nuroot->left; }// nuroot is the minimum, p is its parent if (p != NULL){ p->left = nuroot->right;// give nuroot's only child to p nuroot->right = t2;// nuroot replaces deleted node } nuroot->left = t1;// nuroot replaces deleted node return nuroot; }
Tips for Lab | 42/42 |
Quacks, Recursion, Binary Search Trees
(a[i]+b[j])*c[k] balanced a(a+b]*c unbalanced
newNode()
insert()
Produced: 23 Sep 2015