46
recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

Embed Size (px)

Citation preview

Page 1: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

Round and round recursion: the good, the bad, the ugly, the hidden

ACSE 2006 Talk

Troy VasigaLecturer, University of WaterlooDirector, CCC

Page 2: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 2

Outline

Recursion definedReal-world examples ("The hidden")Benefits ("The good")ExamplesHow it worksPitfalls ("The bad")Larger pitfalls ("The ugly")

Page 3: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 3

Recursion Defined

See "Recursion"

Page 4: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 4

Real Definition

Recursion is defining a function/procedure/structure using the function/procedure/structure itself in the definition

Page 5: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 5

A better definition of Recursion

If you still don't understand recursion, see "Recursion"

Page 6: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 6

A more formal definition

A recursive definition will rely on a recursive definition and some base case(s)

Example: define object X of size n using objects of type X of size k (1 <= k < n)

Page 7: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 7

Example

Babuska (Russian) dolls

Page 8: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 8

Real-World Example

Shells

Page 9: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 9

Real-World Example

Flowers

Page 10: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 10

Real-World Example

Definition of a human I was created by my parents ... who were created by their parents … (religious/biological discussion

follows)

Page 11: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 11

Using Recursion in CS

Less code implies less errorsNatural way of thinking

mathematical inductive reasoning allows both top-down and bottom-up

approaches

Page 12: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 12

(Linked) Lists

C version of linked lists

typedef struct list_elem {

int val;

struct list_elem * next;

} node;

Page 13: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 13

Recursive Ordered Insert

void insert(node** head, int newValue) {

node* newNode = malloc(sizeof(node));

newNode->val = newValue;

newNode->next = NULL;

if (*head == NULL) {

*head = newNode;

} else if ((*head)->next == NULL) {

(*head)->next = newNode;

} else if ((*head)->next->val > newNode->val) {

newNode->next = (*head)->next;

(*head)->next = newNode;

} else {

insert(&(*head)->next, newValue);

}

}

Page 14: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 14

Recursive Length

int length(node* head) {

if (head == NULL) {

return 0;

} else {

return 1+length(head->next);

}

}

Page 15: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 15

Scheme lists

In Scheme a list is the empty list () or a head element, followed by a list

containing the rest of the elementsExamples:

() (1 2 3 4) ((a b) (c d) (e f))

Page 16: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 16

Scheme lists

How to access elements from a list? car = head cdr = tail (rest of the list)

Examples: (car '(a b c)) => a (cdr '(a b c)) => (b c) (car (cdr '(a b c))) => b (caddr '(a b c)) => c

Page 17: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 17

Length in Scheme

(define reclength

(lambda (L)

(if (eq? L '())

0

(+ 1 (reclength (cdr L)))

)

)

)

Page 18: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 18

Am I right?

Prove it!Base case: (length '()) => 0Assume true for list of length k >= 0If length is k+1, our algorithm

computes1+length(list of size k), which it can do

correctly. Our algorithm is correct. Q.E.D.

Page 19: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 19

Trees

Extend linked lists in two dimensions not just "next" but "left" or "right"

Definition A tree is:

empty, oris a node which contains

• a value• a left tree • a right tree

Page 20: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 20

Binary Search Trees

In fact, we will insist the following property is also true: all nodes in the left subtree of a node

are less than or equal to the value in the node

all nodes in the right subtree of a node are greater than the value in the node

Page 21: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 21

Picture

10

96

158

12 23

194

Page 22: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 22

Java code

public class Node

{ private int value;

private Node left;

private Node right;

// other methods are straightforward

}

Page 23: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 23

Using trees recursively

public void insert(Node root, int newValue) {

if (newValue <= root.getValue())

{

if (root.getLeft() == null)

{ root.setLeft(new Node(newValue));

} else

{ insert(root.getLeft(), newValue);

}

} else {

if (root.getRight() == null)

{ root.setRight(new Node(newValue));

} else

{ insert(root.getRight(), newValue);

}

}

}

Page 24: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 24

Inorder traversal

public static void inOrder(Node n)

{

if (n != null)

{

inOrder(n.getLeft());

System.out.print(n.getValue()+" ");

inOrder(n.getRight());

}

}

Page 25: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 25

Inorder observations

Output on original tree4 6 8 9 10 12 15 19 23

Print out "in" the middleWhat if we change the printing part?Exercise: Try to do this without

recursion(Answer: It is really nasty.)

Page 26: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 26

Preorder traversal

public void preOrder(Node n)

{

if (n != null)

{

System.out.print(n.getValue()+" ");

preOrder(n.getLeft());

preOrder(n.getRight());

}

}

Page 27: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 27

Using traversals

Arithmetic expression trees internal nodes are operators leave nodes are operands+

- /

*

2 7

4 10 5

Page 28: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 28

Using traversals

Notice the inorder traversal gives:2 * 7 - 4 + 10 / 5

Notice the preorder traversal gives:+ - * 2 7 4 / 10 5

TI, anyone?

Page 29: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 29

Recursion always works

Theorem: Every iterative loop can be rewritten as a recursive call

Page 30: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 30

How recursion "works"

Implicit call stackEvery call to a function places an

"activation" record on top of the stack in RAM Activation record remember the current

stateStack is built up, and is empty when

we return to the main caller

Page 31: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 31

Avoiding Recursion is Ugly

Consider quicksort Sorts an array into increasing order

Page 32: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 32

Recursive Quicksort

Recursivevoid quicksort (int[] a, int lo, int hi)

{ int i=lo, j=hi, h;

int x=a[(lo+hi)/2];

do { while (a[i]<x) i++;

while (a[j]>x) j--;

if (i<=j)

{ h=a[i]; a[i]=a[j]; a[j]=h;

i++; j--;

}

} while (i<=j);

if (lo<j) quicksort(a, lo, j);

if (i<hi) quicksort(a, i, hi);

}

Page 33: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 33

Iterative Quicksort

QuickSort(A,First,Last)

{ var v,sp,L,L2,p,r,r2;

sp=0;

Push(First,Last);

while( sp > 0 )

{ Pop(L, r)/2;

while( L < r)

{ p = (L+r)/2;

v = A[p].key;

L2 = L;

r2 = r;

while( L2 < r2 )

{ while( A[L2].key < v )

{ L2 = L2+L;

} // ...

Page 34: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 34

More iterative Quicksort

while( A[r2].key > v )

{ r2 = r2-L;

}

if(L2 <= r2 )

{ if(L2 equals r2)

{ Swap(A[L2],A[r2]);

}

L2 = L2 + L;

r2 = r2 - L;

}

} // ...

Page 35: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 35

Yet more iterative Quicksort

if(r2-L > r-L2)

{ if(L<r2)

{ Push(L,r2);

}

L = L2;

} else

{ if(L2 < r)

{ Push(L2,r);

r = r2;

}

}

} // end while( L < r )

} // end while( sp>0 )

} // end QuickSort

Page 36: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 36

Bad Fibonacci, Bad

f(0) = 0f(1) = 1f(n) = f(n-1) + f(n-2)

Page 37: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 37

Dynamic Programming

Recursion leads to a very powerful problem solving technique called Dynamic Programming

Essentially, don't use the recursive call, but write a recurrence relation and solve it from the bottom-up

Page 38: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 38

Shortest Paths using DP

A shortest path is a path between two vertices that has minimum weight

Number the vertices of the graph from 1..n

Let D(k, i, j) mean the shortest path between vertices i and j that uses only vertices 1, …, k

Page 39: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 39

Base case

D(0, i, j) = 0 if i=j w(i,j) if there is an edge (i,j) otherwise

Page 40: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 40

Recursive case

D(k+1, i, j) uses either vertex k+1 or it doesn't

If it doesn't, D(k+1, i, j) = D(k,i,j)

If it does, D(k+1, i, j) = D(k, i, k+1) + D(k, k+1, j)

So, D(k+1,i,j) is the minimum of these two

Page 41: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 41

Filling in the table

In fact, filling in the table is done without using recursion As we did in the Fibonacci case, except

now, we are in more than one dimension

Page 42: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 42

Ugly: Recursive Main

Don't do this in Javapublic class RecUgly

{ public static int factorial(int n)

{ if (n <= 0)

{ return 1;

} else {

return n*factorial(n-1);

}

}

public static void main(String[] args)

{ System.out.println(factorial(11));

}

}

Page 43: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 43

Context-Free Grammars

Describe very complex things using recursion

S -> (S)S -> SSS ->

Page 44: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 44

Mathematical beauty

Koch curves using Lindenmayer systems

Let F mean "forward", + mean "right" and - mean "left"

Koch curve Rule: F -> F-F++F-F (starting with F)

Koch snowflake Start with F++F++F instead!

Page 45: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 45

Dragon curve

X -> X+YF+, Y->-FX-Y (start with FX)

Page 46: Round and round recursion: the good, the bad, the ugly, the hidden ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC

November 18, 2006 ACSE 2006 46

Conclusion

Recursion is Beautiful Natural (in many senses) Mathematically precise Simple Powerful Recursive