0% found this document useful (0 votes)
30 views62 pages

4 - Recursion - V2

Uploaded by

Azenix
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views62 pages

4 - Recursion - V2

Uploaded by

Azenix
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

Recursion

Tanvir Ahmed, PhD


Recursion
• A powerful problem solving strategy
• Definition:
– If the body of a function call the function itself.
• As you can call a function fun1() from a function fun2(), you
are also allowed to call fun1() from fun1().
• What can be the potential problem?:
– Let’s say you are calling fun1 from the body of fun1
– Wouldn’t it be like an infinite loop?
– How can it stop?
– So, inside the body of your function you must put something that
must prevent it to call the function again (i.e., must not result in
a recursive call to prevent to fall in infinite loop).
Example1
void rec2(int x)
{
if (x==0)
return; //this breaking condition will result in poping the function call stack

rec2(x-1);

printf("%d ", x); //this line (including the value of x) is kept in the stack for each call of rec(x-1) in the above line
}

void rec1(int x) int main()


{ {
if (x==0) printf("Calling rec1: ");
return; //breaking condition rec1(10);

printf("%d ", x); //prints first then recursion printf("\nCalling rec2: ");
rec1(x-1); rec2(10);
} }
Output:
Calling rec1: 10 9 8 7 6 5 4 3 2 1
Calling rec2: 1 2 3 4 5 6 7 8 9 10
Explaining Example 1
• Can’t you print the same numbers using a
loop?
Function rec1:
for(i=10; i>0; i--)
printf(“%d” , i);
Function rec2:
for(i=1; i<=10; i++)
printf(“%d” , i);
Analyze rec1 of Example 1
void rec1(int x)
{
if (x==0)
return; //breaking condition

printf("%d ", x); //prints first then recursion


rec1(x-1);
}
• It is a very simple example of recursion.
• The printf prints the value of x at a particular call and then a recursive call is made with x-1, which means
the value of X is decreased by one for the next call.
• As soon as the value of x is 0, the function return to most recent call and prevent it to make the recursive
call again.
• As there is no statement after the recursive call, noting to be kept to execute later.
• call: rec1(10) from main function.
• printf("%d ", 10); call: rec1(9);
• printf("%d ",9); call: rec1(8)
• printf("%d ", 8); call: rec1(7)
• printf("%d ", 7); call: rec1(6)
• printf("%d ", 6); call: rec1(5)
• printf("%d ", 5); call: rec1(4)
• printf("%d ", 4); call: rec1(3)
• printf("%d ", 3); call: rec1(2)
• printf("%d ", 2); call: rec1(1)
• printf("%d ", 1 ); call: rec1(0)
• return to previous call and so on. Actually the function complete its full task after returning to all previous calls. But nothing
was pending for each call in this example
• So, the output is: 10 9 8 7 6 5 4 3 2 1
• Why 0 is not in the output?
Analyze rec2 of Example 1
void rec2(int x)
{
if (x==0)
return; // it is the breaking condition of the recursion call.
rec2(x-1);
printf("%d ", x);
}
• rec2(x-1) is preventing the printf to work while performing the operation of a
particular call.
– So, the lines after rec2(x-1); are kept in a stack.
• call: rec2(10) ->push: printf("%d ", 10);
• call: rec2(9) ->push: printf("%d ", 9);
• call: rec2(8) ->push: printf("%d ", 8);
• call: rec2(7) ->push: printf("%d ", 7);
• call: rec2(6) ->push: printf("%d ", 6);
• call: rec2(5) ->push: printf("%d ", 5);
• call: rec2(4) ->push: printf("%d ", 4);
• call: rec2(3) ->push: printf("%d ", 3);
• call: rec2(2) ->push: printf("%d ", 2);
• call: rec2(1) ->push: printf("%d ", 1);
• call: rec2(0) -> return and keep popping.
• So, the output is: 1 2 3 4 5 6 7 8 9 10
• Why 0 is not in the output?
Example2: Power calculation
• Calculating power be
• It means you need to multiply b (e times). b*b*b*… e times
• Loop based iterative solution:
int Power(int base, int exponent){
long result = 1;

while (exponent != 0)
{
result *= base;
--exponent;
}
return result;
}

• How can you use recursion to do it?


Example2
// Pre-conditions: e is greater than or equal to 0.
// Post-conditions: returns be.
int Power(int base, int exponent) {

if ( exponent == 0 )
return 1;
else
return (base*Power(base, exponent-1));
}

Say we were trying to evaluate the expression:


• Power(5, 2)
• Power(5,2) returns 5*Power(5,2-1) = 5*Power(5,1)
• To evaluate this expression we must evaluate:
• Power(5,1) returns 5*Power(5, 0)
• Finally, we have:
• Power(5,0) returns 1.
• Thus, Power(5,1) returns 5*1, which is 5.
• Finally, Power(5,2) returns 5*Power(5,2-1) = 5*5 = 25,
• and we are done.
General structure of a Recursive Functions
• We can see that in recursion in general:
– when we have a problem, we want to break it down into chunks,
where one of the chunks is a smaller version of the same problem.
• In the case of Power, we utilized the fact that
– xy = x * xy-1, and realized that xy-1 is in essence an easier version of
the original problem.
• We break down our original problem enough that our sub-problem is
quite easy to solve.
– At this point, rather than making another recursive call, directly
return the answer, or complete the task at hand.
• So, ideally, a general structure of a recursive function has a couple
options:
– Break down the problem further, into a smaller subproblem
– OR, the problem is small enough on its own, solve it.
• When we have two options, we often use an if statement. This is
typically what is done with recursion.
General structure of a Recursive Functions
• Here are the two general constructs of recursive functions:
Construct 1
if (terminating condition) {
DO FINAL ACTION
}
else {
Take one step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}
Construct 2
if (!(terminating condition) ) {
Take a step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}

• Typically, functions that return values take on the first construct,


• while void recursive functions use the second construct.
• Note that these are not the ONLY layouts of recursive programs, just common
ones.
Example using construct 1
• Let’s write a function that takes in one positive integer
parameter n, and returns the sum 1+2+...+n. (You probably
did this is C)
• Can you write the iterative solution that you have done in C?

// Pre-condition: n is a positive integer.


// Post-condition: Function returns the sum 1+2+...+n
int Triangle_Number(int n) {
int index, sum = 0;
for (index=1; index <=n; index++)
sum = sum + index;

return sum;
}
Example using construct 1
• Let’s write the recursive solution of the example:
• Step 1: We need to solve this problem is such a way that part of the
solution is a sub-problem of the exact same nature.
• Let f(n) denote the value 1+2+3+...+n
• Using our usual iterative logic, we have:
f(n) = 1 + (2 + 3 + ... + n)
• But, 2+3+... + n IS NOT a sub-problem of the form 1+2+...+n.
• But, let’s try this:
f(n) = 1 + 2 + ... + n = n + (1 + 2 + ... + (n-1))
f(10) = 1 + 2 + ... + 10 = 10 + (1 + 2 + ... + 9) = 10 + f(9)
• So, here we have gotten the expression 1 + 2 + ... + (n-1) which IS a
sub-problem we were looking for.
• Hence, we have
f(n) = 1 + 2 + ... + n = n + (1 + 2 + ... + (n-1)) = n + f(n-1)
Example using construct 1
• If we look at the construct 1, the first thing we need to determine is
a terminating condition.
– We know that f(0) = 0, so our terminating condition can be n=0.
• Furthermore, our recursive call needs to be returning an expression
for f(n) in terms of f(k), for some k<n.
– In this case, we just found that f(n) = n + f(n-1). So, now we can
write our function: can you write it?

// Pre-condition: n is a positive integer.


// Post-condition: Function returns the sum 1+2+...+n
int Triangle_Number(int n) {

if ( n == 0 )
return 0;
else
return (n + Triangle_Number(n-1));
}
Two Other Classic Examples that Use Construct #1
• For positive integers n, n! (read, “n factorial”), is defined as follows:
n! = 1x2x3x4x…xn
• What is a factorial?
– 4! = 4 * 3 * 2 * 1 = 24
– In general, we can say:
– n! = n * (n-1) * (n-2) * … * 2 * 1
• Also, 0! = 1(just accept it!)
• Mathematically, factorial is already defined recursively (Note that each factorial is
related to a factorial of the next smaller integer)
• 4! = 4*3*2*1 = 4 * (4-1)! = 4 * (3!)
• Another example:
– 10! = 10*9*8*7*6*5*4*3*2*1
– 10! = 10 * (9!)
• So:
– n! = n*(n-1)!
– What would be the stopping condition?
– We let 0! = 1;
• Why don’t you write the recursive function?
Two Other Classic Examples that Use Construct #1
• So, the recursive code for factorial would look like this:

#include <stdio.h>
void Fact(int n);
int main(void)
{
int factorial = Fact(10);
printf(“%d\n”, factorial);
return 0;
}

//Here’s the Fact Function


int Fact (int n)
{
if (n == 0) return 1;
else
return (n * Fact(n-1));
}

This program prints the result of 10*9*8*7*6*5*4*3*2*1


Which is:3628800
Slides courtesy: Prof Jonathon’s slides on recursion
Slides courtesy: Prof Jonathon’s slides on recursion
Two Other Classic Examples that Use Construct #1
• Fibonacci numbers are defined recursively, thus,
coding them is quite easy, based on the original
mathematical definition:
• F0 = 0, F1 = 1, Fn = Fn-1 + Fn-2, for all integers n > 1.
• Here is a list:
– 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377,
610,, ...
int fib(int n) {

if (n <= 1)
return n;
else
return fib(n-1) + fib(n-2);
}
Illustration of the Fibonacci recursion process
using recursion tree
Example using construct 2
Construct 2
if (!(terminating condition) ) {
Take a step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}
• Let’s write a function to generate TIP chart:
• Write a function that takes in the lowest dollar value and highest dollar value on
the chart. You know the TIP rate. The method header would look like the:
// The function prints out a chart with the appropriate tips
// for meals ranging from first_val to last_val number of
// dollars, for every whole dollar amount. Both parameters
// must be positive integers.
void Tip_Chart (int first_val, int last_val)
• Now, let’s consider writing this function recursively.
• First, we need to determine a terminating condition.
– if the lowest dollar amount is greater than the highest dollar amount, then the
chart is empty and we are done.
• Next, we need to figure out how to break down our task into two steps: one that
does part of the job, and secondly a recursive step.
Example using construct 2
• Tip Chart:
• What would be the first print out and what is next?
– It is clear that the first value we have to print of the chart is associated with
the lowest dollar value, since that must appear on the chart first.
– Printing out this line of the tip chart can be the part of the job we
accomplish.
• Now, are we left with a sub-problem of the same nature?
– Yes! We simply now need to print a tip chart from the lowest dollar value+1
to the highest dollar value.
Example using construct 2
#define TIP_RATE 0.15

// Pre-condition: Both parameters are integers with the first one being less than or equal to the
second one.
// Post-condition: A tip chart will be printed out, with a row for each dollar amount ranging in
between the value of the two parameters.
void Tip_Chart (int first_val, int last_val)
{

if ( !(first_val > last_val) ) {


printf("On a meal of $%d", first_val);
printf(" you should tip $%lf\n", first_val*TIP_RATE);
Tip_Chart(first_val + 1, last_val);
}
}

int main () On a meal of $1 you should tip $0.150000


{ On a meal of $2 you should tip $0.300000
On a meal of $3 you should tip $0.450000
Tip_Chart(1,10);
On a meal of $4 you should tip $0.600000
On a meal of $5 you should tip $0.750000
} On a meal of $6 you should tip $0.900000
On a meal of $7 you should tip $1.050000
On a meal of $8 you should tip $1.200000
On a meal of $9 you should tip $1.350000
On a meal of $10 you should tip $1.500000
Practice problem
• Write a recursive function that takes a string and
the length of the string in parameters, then print
the string in reverse order.
• The prototype should look like this:
• void print_reverse(char string[], int n)
• If “hello” and 5 is passed, it should print “0lleh”
• What position should be printed first?
– string[n-1]
• What would be the breaking condition?
– If n==1
Solving using construct 1

// Pre-condition: string is a string of length n or greater.


// Post-condition: Prints out the first n characters of string in reverse order.
void print_reverse(char string[], int n) {

// Only one character to print, so print it!


if (n == 1)
printf("%c", string[0]);

// Solve the problem recursively: print the last character, then reverse
// the substring without that last character.
else {
printf("%c", string[n-1]);
print_reverse(string, n-1);
}
}
Solving using construct 2

void printReverse(char word[], int length)


{
if (length > 0)
{
printf(“%c”, word[length-1]);
printReverse(word, length-1);
}
}
Practice Problem
• Write a recursive function that:
• Takes in two non-negative integer parameters
• Returns the product of these parameters
– But it does NOT use multiplication to get the
answer
– So if the parameters are 6 and 4
– The answer would be 24
• Multiplication MxN is actully adding M for N times
• 6*4 = adding 6, 4 times.
• So, 6*4 = 6 + 6 + 6 + 6
• Now write the function.
Practice problem-solution
// Precondition: Both parameters are non-negative integers.
// Postcondition: The product of the two parameters is returned.
int Multiply(int first, int second)
{
if (( second == 0 ) || ( first = 0 ))
return 0;
else
return (first + Multiply(first, second-1));
}

How can you modify it to work for negative number?


int Multiply (int first, int second) { -Example: if you calculate 4 * -3, the program converts
the result to negative and make -3 to +3 and then use
if ( second < 0 ) the usual recursion in the else statement
return -Multiply(first,-second); - Example: if you calculate -4 * 3, the program
else if ( first < 0 ) converts the result to negative and make -4 to +3
and then use the usual recursion in the else
return -Multiply(-first, second); statement
else if (( second == 0 ) || ( first = 0 )) - Example: if you calculate -4 * -3, the program
return 0; converts the result to negative and make -3 to +3
- In the next call, it converts the result to
else negative again (which makes the result
return (first +Multiply(first, second-1)); positive) and converts -4 to +4. Then it uses
the usual recursion in the else statement
}
More exercises
• 1) Write a recursive function that determines the
nth Lucas number. Here is the definition of the
Lucas numbers:

• L1 = 1, L2 = 3, Ln = Ln-1 + Ln-2, for all integers n > 2.



• // Pre-condition: n > 0
• // Post-condition: Returns the nth Lucas number, Ln.

int Lucas(int n);


nth Lucas number
// n'th Lucas number
#include <stdio.h>

// recursive function
int lucas(int n)
{
// Base cases
if (n == 1)
return 1;
else if (n == 2)
return 3;
else
return lucas(n - 1) + lucas(n - 2);
}

// Driver Code
int main()
{
int n = 9;
printf("%d", lucas(n));
return 0;
}
Try this
• How can you use recursion to convert and
print Decimal to Binary?
• Remember the steps: division and reminder
technique.
• The reminders should be printed from bottom
to top.
• Next slide is copied from Number system slide
to remind you about the steps
• Converting from base 10 to a new base
(division- remainder technique)
11710 = ?2

Step Operation Result (n/base) Remainder (n%base)

Step 1 117 / 2 58 1

Step 2 58 / 2 29 0

Step 3 29/ 2 14 1

Step 4 14 / 2 7 0

Step 5 7/2 3 1

Step 6 3/2 1 1
Read reverse order 11101012

2/13/2020 Tanvir Ahmed 31


Decimal to Binary

void dectobin(int n) {

if (n < 2)
printf("%d", n);

else {
dectobin(n/2);
printf("%d", n%2);
}
}
Towers of Hanoi
• Problem:
• we have:
• three rods ( or tower)
• n disks in the left most tower. The disks are arranged with
the largest diameter disks at the bottom

• Some monk has the daunting task of moving disks from one
tower to another tower
– Often defined as moving from Tower #1 to Tower #3
• Tower #2 is just an intermediate pole

– He can only move ONE disk at a time


– And he MUST follow the rule of NEVER putting a bigger disk on
top of a smaller disk
Towers of Hanoi
• Steps:
• Take an example for 2 disks :
• Let rod 1 = 'A', rod 2 = 'B', rod 3 = 'C'.

• Step 1 : Shift first disk from 'A' to 'B'.


• Step 2 : Shift second disk from 'A' to 'C'.
• Step 3 : Shift first disk from 'B' to 'C'.

• The pattern here is :


• Shift 'n-1' disks from 'A' to 'B'.
• Shift last disk from 'A' to 'C'.
• Shift 'n-1' disks from 'B' to 'C'.
illustration for 3 disks :
illustration for 3 disks :
Towers of Hanoi
• Input : 2
Output :
Disk 1 moved from A to B
Disk 2 moved from A to C
Disk 1 moved from B to C

• Input : 3
Output :
Disk 1 moved from A to C
Disk 2 moved from A to B The pattern here is :
Disk 1 moved from C to B Shift 'n-1' disks from 'A' to 'B'.
Disk 3 moved from A to C Shift last disk from 'A' to 'C'.
Shift 'n-1' disks from 'B' to 'C'.
Disk 1 moved from B to A
Disk 2 moved from B to C
Disk 1 moved from A to C
Towers of Hanoi
#include <stdio.h>

void towerOfHanoi(int n, char from_rod, char to_rod, char aux_rod)


{
if (n == 1)
{
printf("\n Move disk 1 from rod %c to rod %c", from_rod, to_rod);
return;
}
towerOfHanoi(n-1, from_rod, aux_rod, to_rod);
printf("\n Move disk %d from rod %c to rod %c", n, from_rod, to_rod);
towerOfHanoi(n-1, aux_rod, to_rod, from_rod);
}

int main()
{
int n = 4; // Number of disks
towerOfHanoi(n, 'A', 'C', 'B'); // A, B and C are names of rods
return 0;
}
Output:
Move disk 1 from rod A to rod B
Move disk 2 from rod A to rod C
Move disk 1 from rod B to rod C
Towers of Hanoi
Move disk 3 from rod A to rod B
Move disk 1 from rod C to rod A For n disks, total 2n – 1 moves are required.
Move disk 2 from rod C to rod B
Move disk 1 from rod A to rod B eg: For 4 disks 24 – 1 = 15 moves are required.
Move disk 4 from rod A to rod C
Move disk 1 from rod B to rod C For n disks, total 2n-1 function calls are made.
Move disk 2 from rod B to rod A
Move disk 1 from rod C to rod A eg: For 4 disks 24-1 = 8 function calls are made.
Move disk 3 from rod B to rod C
Move disk 1 from rod A to rod B
Move disk 2 from rod A to rod C
Move disk 1 from rod B to rod C
Illustration of the
recursion
Fast Exponent
int Power(int base, int exponent) {

if ( exponent == 0 )
return 1;
else
return (base*Power(base, exponent-1));
}
• Our recursive power function works just fine
• But, it becomes VERY slow for large exponents
– If the exponent was 10,000, that would be 9,999
multiplications!
• How can we do better?
– Rememer the laws of exponents:
• 28 = 24 * 24
• Now 24 = 22 * 22
• And 22 = 2 * (2)
– So: 2*(2) = 4, 4*(4) = 16, 16*(16) = 256 = 28
– So we’ve calculated 28 using only three multiplications
– MUCH better than 7 multiplications
Fast Exponent
• So, we see that bn = bn/2 * bn/2
• It will be log n number of multiplication (much better than n
multiplication)
• But can you guess what problem we have here: bn = bn/2 * bn/2
• It works when n is even. How about if n is not even?
• See: 29= 24*24*2
• So, we need to handle this case. We can say:

• Also note that this method relies on integer division.


– if n is 9, then n/2 = 4
• So, can you write the code?
Fast Exponent
int powerB(int base, int exp)
{
if (exp == 0)
return 1;
if (exp == 1)
return base;
if (exp%2 == 0) //if exp is even
return powerB(base*base, exp/2);
else //if exp is odd
return powerB(base*base, exp/2) *base;
}

int main()
{
printf("%d", powerB(2,5));

return 0;
}
Let us try to find the result of f(4) for
the following recursive function using
recursion tree
int f(int n)
{
int ans;
int i;
if(n<3)
return n;
ans = f(n/2);
for(i=0; i<n; i++)
ans += f(i);
return ans;
}
int f(int n)
{
int ans;
int i;
if(n<3)
return n;
ans = f(n/2);
for(i=0; i<n; i++)
ans += f(i);
return ans;
}
More Recursion: Permutations
• The permutation problem is as follows:
• Given a list of items,
– list all the possible orderings of those items.
– The items can be numbers or letters or other object
• For example: all the permutations of 0,1,2:
• 0, 1, 2
• 0, 2, 1
• 1, 0, 2
• 1, 2, 0
• 2, 0, 1
• 2, 1, 0.
• Another example: All the permutations of the letters CAT:
CAT ACT TAC
CTA ATC TCA

• How can we write a program to generate these permutations?


Permutations
• There are several different permutation algorithms, but
since recursion an emphasis of the course, a recursive
algorithm to solve this problem will be presented.
• The permutation algorithm:
– We want to list all the permutations of “CAT”
– So, let’s split our task into 3 groups of
permutations.
a) Permutations that start with C
b) Permutations that start with A
c) Permutations that start with T

CAT ACT TAC


CTA ATC TCA
Permutations
Permutations that start with C:
 Think about recursion and how can we reduce the
problem to a smaller problem of same form
 Permutations starts with C are 3-character strings
that form by putting C in the beginning of all
permutations of “AT”
 So, it means we need to do another permutation,
which is smaller and it should be in the same form!
CAT
CTA

 So, two things to note here:


 We will use recursion for generating the
permutations
 We need to do it for each of the starting letter.
Permutations
 As we have split our task in the 3 groups as we
have 3 letters in CAT.
 We will need 3 recursive calls, one for each letter
 If we were permuting the letters of the word
“science”, we could need
 Eight recursive calls, one for each possible starting
letter.
 So, we will need a for loop in our algorithm:
for (each possible starting letter)
{
list all permutations that start with that letter
}
Permutations
 What would be the terminating condition for your
recursion?
 If we have only 0 or 1 element, there is nothing to
permute
 We will use 0 as the terminating condition
 It means when there is only 0 element left, we break our
recursion
 The function prototype should look like this:
// Pre-condition: str is a valid C String, and k is non-negative and
// less than or equal to the length of str.
// Post-condition: All of the permutations of str with the first k
// characters fixed in their original positions are
// printed. Namely, if n is the length of str, then
// (n-k)! permutations are printed.
void RecursivePermute(char str[], int k);

So k refers to the first k characters that are fixed in their original


positions
Permutations
 What would be the terminating condition for your recursion?
 Remember, k refers to the first k characters that are fixed
 So, we should terminate when k is equal to the length of the string,
str
 So, when the terminating condition occurs, we simply want to print
out our permutation
 If the terminating condition is not met,
 We use a for loop that tries each character at index k.
 The main loop will look like this:
for (j=k; j<strlen(str); j++) {
ExchangeCharacters(str, k, j);
RecursivePermute(str, k+1);
ExchangeCharacters(str, j, k);
}
- Now how do we get different characters (the ‘C’, the ‘A’, and the ‘T’) at the
first position?
- C is the first character in the word CAT
- So how do we make ‘A’ become the first character
Permutations
for (j=k; j<strlen(str); j++) {
ExchangeCharacters(str, k, j);
RecursivePermute(str, k+1);
ExchangeCharacters(str, j, k);
}

• ExchangeCharacters function:
– This function will take in the string (str) and it will swap
two characters within that string.
– The character at index k will swap with the one at index j

// Pre-condition: str is a valid C String and i and j are valid indexes to that
string.
// Post-condition: The characters at index i and j will be swapped in str.
void ExchangeCharacters(char str[], int i, int j) {
char temp = str[i];
str[i] = str[j];
str[j] = temp;
}
Permutations
for (j=k; j<strlen(str); j++) {
ExchangeCharacters(str, k, j);
RecursivePermute(str, k+1);
ExchangeCharacters(str, j, k);
}

• ExchangeCharacters function:
– Remember: We need to find all permutations
with C as the first character, A as the first, and
with T as the first (for “CAT”)
– The ExchangeCharacters function swaps the two
characters at the indices passed in.
– We then recursively call the permute function
– Then we swap the characters back to their spots.
Permutations
void RecursivePermute(char str[], int k) {

int j;
// Base-case: Since all letters are fixed, we can ONLY print what's stored in str.
if (k == strlen(str))
printf("%s\n", str);

else {
// Loop through each possible starting letter for index k, the first index for which we have a choice.
for (j=k; j<strlen(str); j++) {
// Place the character stored in index j in location k.
ExchangeCharacters(str, k, j);

// Print out all of the permutations with that character just chosen above fixed.
RecursivePermute(str, k+1);

// Put the original character that used to be there back in its place.
ExchangeCharacters(str, j, k);
}
}
}
Permutation
void RecursivePermute(char str[], int k) {

int j;
// Base-case: Since all letters are fixed, we can ONLY print what's stored in str.
if (k == strlen(str))
printf("%s\n", str);

• Let’s discuss the code:


– We sent our string and k to this function.
– From the main function we just passed k=0
– Remember, k represents the first k characters that are fixed at
their spots
– So for the first time in our example we passed:
• CAT and k=0
– The base case says if k becomes the length of our string, it
means all characters are fixed
• In such case no permutation is needed and we print out the resulting
string
Permutation
void RecursivePermute(char str[], int k) {
// previous code here
else {
// Loop through each possible starting letter for index k, the first index for which
we have a choice.
for (j=k; j<strlen(str); j++) {
// // our code here

• Let’s discuss the code:


– So, all other cases it means if all characters are
not fixed yet
• We need to permute more
• We have to try the character at position k
• So, we go to the loop
Permutation
• In the loop it iterates and use the possible characters
that can go into index k
• Remember, k refers to the number of fixed positions.
– If k is 2, it means index 0 and index 1 are fixed
– Then the first non-fixed location is index 2, so the valu eof
k is 2

for (j=k; j<strlen(str); j++) {


// Place the character stored in index j in location k.
ExchangeCharacters(str, k, j);

// Print out all of the permutations with that character just chosen above fixed.
RecursivePermute(str, k+1);

// Put the original character that used to be there back in its place.
ExchangeCharacters(str, j, k);
}
Permutation
• For all possible chracters tht could be placed at
index k:
– ExchangeCharacters (str, k, j)
– It means swap the charcaters at index k and j
– Meaning, try all possible (remaining) values at index k

for (j=k; j<strlen(str); j++) {


// Place the character stored in index j in location k.
ExchangeCharacters(str, k, j);

// Print out all of the permutations with that character just chosen above fixed.
RecursivePermute(str, k+1);

// Put the original character that used to be there back in its place.
ExchangeCharacters(str, j, k);
}
Permutation
• For all possible characters at index k:
– So for our example for the first time:
• Input was CAT for the starting and k = 0;
• This loop would run three times(length of CAT=3)
– Each time, the first line would try each character at index 0
– It means C will be at 0, then A will be at 0 and then T will be at 0

for (j=k; j<strlen(str); j++) {


// Place the character stored in index j in location k.
ExchangeCharacters(str, k, j);

// Print out all of the permutations with that character just chosen above fixed.
RecursivePermute(str, k+1);

// Put the original character that used to be there back in its place.
ExchangeCharacters(str, j, k);
}
Permutation
• So, the for loop iterates three times (for CAT)
– First line of code makes each letter the first spot of the
string
– The second line then recursively calls the function
• The arguments are string (updated with a new, 1st character)
• And the new value of k (referring to the #of Fixed spots)
– Third and final line of code simply switches back he
characters that we swapped with the first line of code (of
the for loop)
for (j=k; j<strlen(str); j++) {
// Place the character stored in index j in location k.
ExchangeCharacters(str, k, j);

// Print out all of the permutations with that character just chosen above fixed.
RecursivePermute(str, k+1);

// Put the original character that used to be there back in its place.
ExchangeCharacters(str, j, k);
}
Permutation
• The full code is available here:
https://www.cs.ucf.edu/courses/cop3502/spr2012
/programs/recursion/permute.c
- A tracing code is available here:
https://www.cs.ucf.edu/courses/cop3502/spr2012
/programs/recursion/permute2.c

- Prof Arup’s note on permutation(self study):


http://www.cs.ucf.edu/~dmarino/ucf/transparency
/cop3502/lec/RecursionPermutations.doc
References
• Tower of Hanoi: https://www.geeksforgeeks.org/c-program-for-
tower-of-hanoi/
• Arup Guha’s notes:
– http://www.cs.ucf.edu/~dmarino/ucf/transparency/cop3502/lec/Rec
ursionIntro.doc
– http://www.cs.ucf.edu/~dmarino/ucf/transparency/cop3502/lec/Rec
ursionTowers.doc
– http://www.cs.ucf.edu/~dmarino/ucf/transparency/cop3502/lec/Rec
ursionFastExp.doc
– http://www.cs.ucf.edu/~dmarino/ucf/transparency/cop3502/lec/Rec
ursionFloodFill.doc
– http://www.cs.ucf.edu/~dmarino/ucf/transparency/cop3502/lec/Rec
ursionPermutations.doc
• Many example functions in one c code:
http://www.cs.ucf.edu/~dmarino/ucf/transparency/cop3502/samp
leprogs/recursion.c

You might also like