Вы находитесь на странице: 1из 16

CS103L SPRING 2017

UNIT 8: RECURSION
TEXT

RECURSION
▸ A recursion function is defined in terms of itself

▸ Applies to math, e.g. recursion relations, sequences

▸ Fibonacci: F0 = 1, F1 = 1, Fn = Fn-1 + Fn-2

▸ Applies to computer functions that call themselves

▸ Also, nerdy CS acronyms

▸ GNU = GNU is Not Unix


TEXT

RECURSIVE FUNCTIONS
▸ To write recursive functions we break up the problem into two cases:

▸ #1 A smaller version of the same problem

▸ #2 A “base case” of the problem where the answer is known ahead of time, or easily computed

▸ All recursive functions *must* have a base case - or what?

▸ Factorial Example: n! = n*(n-1)*(n-1)…*1

▸ factorial(n):

▸ factorial(1) = 1 (base case)

▸ factorial(n) = n*factorial(n-1) (recursive case)


TEXT

FACTORIAL EXAMPLE
unsigned long fact(unsigned long n)

//base case

if(n == 1) return 1;

unsigned long r = fact(n-1); //recursive case

return n * r

}
TEXT

TRACING RECURSIVE CODE

fact(n=3) fact(n=2) fact(n=1)

r = fact(n-1) r = fact(n-1) return 1

return 3 * 2 return 2 * 1
TEXT

TWO TYPES OF RECURSIVE FUNCTIONS


▸ Recursive functions can be classified in two type: head recursion, tail recursion

▸ Head Recursion: immediately make the recursive call then do some work

▸ Tail recursion: do some work, then make the recursive call


void stopgo(int n) void gostop(int n)

{ {

if(n==1) { if(n==1) {

cout << “Stop.” << endl; cout << “Stop.” << endl;

return;
 return;

} }

gostop(n-1); cout << “Go” << endl;

cout << “Go” << endl; gostop(n-1);

} }
TEXT
int main()

{ 

RECURSIVE FUNCTIONS int data[4] = {8, 6, 7, 9}; 

int sum1 = isum_it(data, 4);

int sum2 = rsum_it(data, 4);

▸ Recursive functions usually take the place of }
loops int isum_it(int data[], int len)

{

sum = data[0];

▸ Example: summing up an array of integers for(int i=1; i < len; i++){

sum += data[i];

}

}

int rsum_it(int data[], int len)



{

if(len == 1)

return data[0];

else 

int sum = rsum_it(data, len-1);

return sum + data[len-1];

}
TEXT

TRACING RECURSIVE SUM

data[4] =
{8,6,7,9};
rsum_it(data, 4) rsum_it(data, 3) rsum_it(data, 2) rsum_it(data, 1)

int sum = int sum = int sum = return data[0]


rsum_it(data, 4-1) rsum_it(data, 3-1) rsum_it(data, 2-1)

sum = 21 sum = 14 sum = 8

return 21 + data[3] return 14 + data[2] return 8+data[1]


System
tem StackStack & Recursion
& Recursion
int main() int main()
{
{
tack
tem makes
stack recursion
TEXT makes recursion
int data[4] = {8, 6, 7, 9};
int data[4]
int sum2 = rsum_it(data, 4); = {8, 6, 7, 9};
int sum2 = rsum_it(data, 4);
roviding separate }
eage
byfor
providing
the local
separate }
int rsum_it(int data[], int len)
{

each
STACK
y storage MAKES
runningfor
RECURSION POSSIBLE
int rsum_it(int data[], int len)
the local return data[0];
instance
if(len == 1)
{
if(len == 1)
es
on ▸
of How
each does this
running work: we
instance
else call
int sum =
the *same*
return function over and over?
data[0];
else
rsum_it(data, len-1);
unction
▸ Because of the stack! We can call the function as many times as need be,
int sum =
return sum + data[len-1];
} rsum_it(data, len-1);
each gets its *own* stack
Code for all functions
frame: hence
return sum + each has it’s
data[len-1]; own stack-local variables
}
Code
forfor all functions 800
ata rsum_it
Code(data=800,
for all functions int main()

=1, sum=??) and return link 8 6 7 9
{ 

ata for rsum_it (data=800, data[4]: 0 1 2 3
n=2,
=2, sum=??)
sum=8) Code
Data for
and
and for
returnall
rsum_it
return link
linkfunctions
(data=800, 800 int data[4] = {8, 6, 7, 9}; 

ata forlen=1,
rsum_itsum=??) and return link
(data=800, 8 6 int
7 9 sum2 = rsum_it(data, 4);

=3, sum=14)
sum=??) and return link }
Data for rsum_it (data=800, data[4]: 0 1 2 3
ata forlen=2,
rsum_it (data=800,
len=2, sum=??)
sum=8) and
and return
return link
link
=4, sum=21)
sum=??) and return link int rsum_it(int data[], int len)

for main Data for rsum_itand(data=800,
(data=800,sum2=??) {

len=3, sum=??) and return link
sum=14)
return link
if(len == 1)

Data
System forarea
stack rsum_it (data=800,
len=4, sum=21)
sum=??) and return link
return data[0];

Data for main (data=800,sum2=??) and
else 

return link int sum = rsum_it(data, len-1);

return sum + data[len-1];

System stack area
}
TEXT

IN CLASS EXERCISE
▸ count-up

▸ count-down
TEXT

REQUIREMENTS FOR RECURSIVE FUNCTIONS


▸ You must have at least one base case!

▸ This case must terminate the recursion, i.e it will not make a further recursive
call

▸ It is possible to have more than one base case

▸ The recursive case must “make progress” towards the base case

▸ The problem must get “smaller” each time… or?

▸ Recursive cases and base cases must have return statements to propagate the
answer “up” the recursive call stack
TEXT

LOOPS VS. RECURSION


▸ FAQ: is it better to use loops or recursion?

▸ All recursive solutions can be done with iterative solutions

▸ Recursion pros:

▸ Clean and elegant code, easy to read

▸ Usually recursive code is much simpler than iterative

▸ Sometime iterative code is *nearly impossible* to write!

▸ Power of recursion comes from making multiple recursive calls - hard to implement with iterative solutions

▸ How to choose?

▸ Iteration is faster/less memory

▸ But if implementation is difficult or inscrutable - use recursion


14

Recursive Binary Search


TEXT

k = 11
• Assume
RECURSIVE remaining items = [start, end)
EXAMPLES List 2 3 4 6 9 11 13 15 19
– start is inclusive index of start item in remaining list index 0 1 2 3 4 5 6 7 8

▸ Recursive Binary – End is exclusive index of start item in remaining list


Search start i end
• binSearch(target, List[], start, end)
▸ Is a given element, k, in an array? If yes, return index, otherwise return -1
List 2 3 4 6 9 11 13 15 19
– end
▸ Initialize start, mid, Perform base check (empty list) index 0 1 2 3 4 5 6 7 8

• Return NOT FOUND (-1)


▸ binsearch(k, list, start, end): start i end

– Pick mid item
base case: start = end
List 2 3 4 6 9 11 13 15 19
– Based on comparison of k with List[mid]
return list[start] == k ? start : -1 index 0 1 2 3 4 5 6 7 8

• EQ => Found => return mid
▸ Recursive case: start i end
• LT => return answer to BinSearch[start,mid)
▸ compute mid • GT => return answer to BinSearch[mid+1,end)
List 2 3 4 6 9 11 13 15 19
▸ if (list[mid] == k) return mid; index 0 1 2 3 4 5 6 7 8

▸ else if(list[mid] > k) return binsearch(k,list,start,mid);


start end
▸ else return binsearch(k,list,mid,end); i
15

Sorting
TEXT

• If we have an unordered list, sequential List 7 3 8 6 5 1


RECURSIVE EXAMPLES
search becomes our only choice index 0 1 2 3 4 5
Original

▸ Recursive•Bubble
If we Sort
will perform a lot of searches it may List
index
3 7 6 5 1 8
0 1 2 3 4 5
be beneficial to sort the list, then use After Pass 1
▸ List with indexes 0 -search
binary (n-2)
List 3 6 5 1 7 8

• Many
▸ Scan list and swap sorting algorithms
to “bubble” largest of differing
value to the right
index 0 1 2 3 4 5
After Pass 2
complexity (i.e. faster or slower)
▸ Recurse on list indexes 0 - (n-2), then 0 - (n - 3), etc. List 3 5 1 6 7 8
• Bubble Sort (simple though not terribly index 0 1 2 3 4 5
After Pass 3
efficient)
List 3 1 5 6 7 8
– On each pass through thru the list, pick up the index 0 1 2 3 4 5
maximum element and place it at the end of After Pass 4
the list. Then repeat using a list of size n-1 (i.e. List 1 3 5 6 7 8
w/o the newly placed maximum value) index 0 1 2 3 4 5
After Pass 5
TEXT

IN CLASS EXERCISE
▸ Text Fractal
TEXT

CODING TIME!
▸ Examples to code: ▸ Examples to code:
▸ recursive sum ▸ Recursive Insertion sort
▸ index version
▸ Fibonacci
▸ pointer version

▸ Recursive binary search

▸ index version

▸ pointer version

▸ Recursive Bubble sort

Оценить