Upload
ashlyn-shawley
View
214
Download
1
Embed Size (px)
Citation preview
ECE 103 Engineering ProgrammingChapter 54Recursion
Herbert G. Mayer, PSU CSStatus 6/4/2014
Initial content copied verbatim fromECE 103 material developed by
Professor Phillip Wong @ PSU ECE
3
Recursion Process
A recursive function is a function that invokes itself.
Recursion is a powerful and elegant method to solve certain types of problems.
Recursion decomposes a problem into smaller subproblems of exactly the same form as the original problem.
5
Function call mechanics:
When a function is called, these items are saved (pushed) onto a call stack: Return address Function parameters Local data
When the function is done: The stored items are removed (popped) from the call
stack. Control returns back to the code following the original
call.
6
Recursive function call:
Pending function data are placed on the call stack each time the function invokes itself.
A base case determines when recursion stops. It is a conditional test that halts recursion when:
The problem cannot be decomposed any further. A predefined recursion depth is reached.
Once the base case is reached, the recursion begins backtracking to return pending values.
7
#include <stdio.h>
/* This function adds up the numbers from 1 to n using ITERATION */int sum (int n){
int psum = 0; /* Partial sum accumulator */int k;
for (k = 1; k <= n; k++) /* Iteration */psum = psum + k;
return psum;}
int main (void){
printf("\nFinal sum(5) = %d\n", sum(5));return 0;
}
ACTUAL OUTPUT:
sum(5) = 15
8
#include <stdio.h>
/* This function adds up the numbers from 1 to n using RECURSION */int sum (int n){
printf("sum(%d) = ", n);if (n <= 1) /* Base case */{
printf("1\n");return 1;
}else /* Recursion */{
printf("%d + sum(%d)\n", n, n-1);return n + sum(n - 1);
}}
int main (void){
printf("\nFinal sum(5) = %d\n", sum(5));return 0;
}
ACTUAL OUTPUT:sum(5) = 5 + sum(4)sum(4) = 4 + sum(3)sum(3) = 3 + sum(2)sum(2) = 2 + sum(1)sum(1) = 1
→ sum(5) = 15
9
Potential Problems:
Deep recursion may require excessive memory storage.
Recursion can be inefficient due to excessive recomputation.
If the base case is never satisfied, the recursion is infinite (until all memory becomes exhausted).
Recursion may not converge if the subproblems do not become smaller.
10
Fibonacci Sequence Fn = { 0 for n=0, 1 for n=1, and Fn-1 + Fn-2 for n>=2 }
→ 0, 1, 1, 2, 3, 5, 8, 13, 21, … /* This is the iterative (non-recursive) version */long int fib (int n){
long int previous = -1;long int result = 1;long int sum;int i;
for (i = 0; i <= n; ++i){
sum = result + previous;previous = result;result = sum;printf("i=%d sum=%ld previous=%ld result=%ld\n", i, sum, previous, result);
}
return result;}
ACTUAL OUTPUT FOR fib(5):i=0 sum=0 previous=1 result=0i=1 sum=1 previous=0 result=1i=2 sum=1 previous=1 result=1i=3 sum=2 previous=1 result=2i=4 sum=3 previous=2 result=3i=5 sum=5 previous=3 result=5
11
/* This is the recursive version */long int fib (int n){
if ( n == 0 || n == 1 )/* base case */return n;
else/* recursion */return fib(n-1) + fib(n-2);
}
Order of calls for fib(5):
fib(5)= fib(4) + fib(3) fib(4)=fib(3) + fib(2)
fib(3)=fib(2) + fib(1)
fib(2)=fib(1) + fib(0)
fib(1)= 1
fib(0) = 0
fib(1)= 1
fib(2)=fib(1) + fib(0)
fib(1)= 1
fib(0) = 0
fib(3)=fib(2) + fib(1)
fib(2)=fib(1) + fib(0)
fib(1)= 1
fib(0) = 0
Tail-recursive functions can always be rewritten as iterative functions.
(Tail-recursive means the recursion occurs in the last statement.)
12
Quicksort
Quicksort is a sorting algorithm developed by Tony Hoare in 1960. On average, it makes O(n log n) comparisons to sort n items.
Quicksort partitions data into two smaller sub-lists and then recursively sorts each sub-list.
13
From: Wikipedia article Quicksort (in-place version)
Partition Function
// left is the index of the leftmost element of the subarray// right is the index of the rightmost element of the subarray (inclusive)// number of elements in subarray = right-left+1
function partition (array, left, right, pivotIndex)pivotValue := array[pivotIndex]swap array[pivotIndex] and array[right] // Move pivot to endstoreIndex := left
for i from left to right – 1 // left ≤ i < rightif array[i] <= pivotValue
swap array[i] and array[storeIndex]storeIndex := storeIndex + 1
swap array[storeIndex] and array[right] // Move pivot to its final placereturn storeIndex
14
Sorting Function function quicksort(array, left, right)
// If the list has 2 or more itemsif left < right
choose any pivotIndex such that left ≤ pivotIndex ≤ right
// Get lists of bigger and smaller items and final position of pivot
pivotNewIndex := partition(array, left, right, pivotIndex)
// Recursively sort elements smaller than the pivotquicksort(array, left, pivotNewIndex - 1)
// Recursively sort elements at least as big as the pivotquicksort(array, pivotNewIndex + 1, right)
15
Sierpinski Triangle
From: http://www.cse.nd.edu/~dthain/courses/cse20211/fall2011/lab5
Each triangle is recursively divided into four sub-triangles:
•one at each corner•one in the center
16
Graphics Support:
Using a graphics library, we write a function to draw a single triangle:
void draw_triangle (float x1, float y1, float x2, float y2, float x3, float y3)
{
/* Replace these with commands of actual graphics library */
draw_line( x1,y1, x2,y2 );
draw_line( x2,y2, x3,y3 );
draw_line( x3,y3, x1,y1 );
}
(x1,y1)
(x2,y2)
(x3,y3)
17
Step 1 of recursion function:
Define the drawing step.
void fractal_triangle (float x1, float y1, float x2, float y2, float x3, float y3)
{
/* Base case will go here */
/* Drawing step */
draw_triangle( x1,y1, x2,y2, x3,y3 );
/* Recursive step will go here */
}
(x1,y1)
(x2,y2)
(x3,y3)
18
Step 2 of recursion function:
Define the recursion step.
void fractal_triangle (float x1, float y1, float x2, float y2, float x3, float y3)
{
/* Base case will go here */
/* Drawing step */
draw_triangle( x1,y1, x2,y2, x3,y3 );
/* Recursive step */
fractal_triangle( x1,y1, (x1+x2)/2,(y1+y2)/2, (x1+x3)/2,(y1+y3)/2 );
fractal_triangle( (x1+x2)/2,(y1+y2)/2, x2,y2, (x2+x3)/2,(y2+y3)/2 );
fractal_triangle( (x1+x3)/2,(y1+y3)/2, (x2+x3)/2,(y2+y3)/2, x3,y3 );
}
(x1,y1)
(x2,y2)
(x3,y3)
19
Step 3 of recursion function:
Define the base case.
void fractal_triangle (float x1, float y1, float x2, float y2, float x3, float y3)
{
/* Base case step */
if ( fabs(x2 – x1) < LIMIT ) /* Stop when side length gets too short */
return;
/* Drawing step */
draw_triangle( x1,y1, x2,y2, x3,y3 );
/* Recursive step */
fractal_triangle( x1,y1, (x1+x2)/2,(y1+y2)/2, (x1+x3)/2,(y1+y3)/2 );
fractal_triangle( (x1+x2)/2,(y1+y2)/2, x2,y2, (x2+x3)/2,(y2+y3)/2 );
fractal_triangle( (x1+x3)/2,(y1+y3)/2, (x2+x3)/2,(y2+y3)/2, x3,y3 );
}
(x1,y1)
(x2,y2)
(x3,y3)