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

Post on 09-Jan-2016

29 views 1 download

description

Round and round recursion: the good, the bad, the ugly, the hidden. ACSE 2006 Talk Troy Vasiga Lecturer, University of Waterloo Director, CCC. Outline. Recursion defined Real-world examples ("The hidden") Benefits ("The good") Examples How it works Pitfalls ("The bad") - PowerPoint PPT Presentation

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

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

ACSE 2006 Talk

Troy VasigaLecturer, University of WaterlooDirector, 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")

November 18, 2006 ACSE 2006 3

Recursion Defined

See "Recursion"

November 18, 2006 ACSE 2006 4

Real Definition

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

November 18, 2006 ACSE 2006 5

A better definition of Recursion

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

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)

November 18, 2006 ACSE 2006 7

Example

Babuska (Russian) dolls

November 18, 2006 ACSE 2006 8

Real-World Example

Shells

November 18, 2006 ACSE 2006 9

Real-World Example

Flowers

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)

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

November 18, 2006 ACSE 2006 12

(Linked) Lists

C version of linked lists

typedef struct list_elem {

int val;

struct list_elem * next;

} node;

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);

}

}

November 18, 2006 ACSE 2006 14

Recursive Length

int length(node* head) {

if (head == NULL) {

return 0;

} else {

return 1+length(head->next);

}

}

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))

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

November 18, 2006 ACSE 2006 17

Length in Scheme

(define reclength

(lambda (L)

(if (eq? L '())

0

(+ 1 (reclength (cdr L)))

)

)

)

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.

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

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

November 18, 2006 ACSE 2006 21

Picture

10

96

158

12 23

194

November 18, 2006 ACSE 2006 22

Java code

public class Node

{ private int value;

private Node left;

private Node right;

// other methods are straightforward

}

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);

}

}

}

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());

}

}

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.)

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());

}

}

November 18, 2006 ACSE 2006 27

Using traversals

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

- /

*

2 7

4 10 5

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?

November 18, 2006 ACSE 2006 29

Recursion always works

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

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

November 18, 2006 ACSE 2006 31

Avoiding Recursion is Ugly

Consider quicksort Sorts an array into increasing order

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);

}

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;

} // ...

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;

}

} // ...

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

November 18, 2006 ACSE 2006 36

Bad Fibonacci, Bad

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

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

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

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

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

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

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));

}

}

November 18, 2006 ACSE 2006 43

Context-Free Grammars

Describe very complex things using recursion

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

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!

November 18, 2006 ACSE 2006 45

Dragon curve

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

November 18, 2006 ACSE 2006 46

Conclusion

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