Loading...

PPT – Recursion PowerPoint presentation | free to download - id: 1d9ec4-ZDc1Z

The Adobe Flash plugin is needed to view this content

Chapter 19

- Recursion

19.1 Introduction to Recursion

- A recursive function is one that calls itself.

void message(void) cout ltlt "This is a

recursive function.\n" message()

The function above displays the string "This is a

recursive function.\n", and then calls

itself. Can you see a problem with the function?

Recursion

- The function is like an infinite loop because

there is no code to stop it from repeating. - Like a loop, a recursive function must have some

algorithm to control the number of times it

repeats.

Recursion

- Like a loop, a recursive function must have some

algorithm to control the number of times it

repeats. Shown below is a modification of the

message function. It passes an integer argument,

which holds the number of times the function is

to call itself.

void message(int times) if (times gt

0) cout ltlt "This is a recursive

function.\n" message(times - 1) return

Recursion

- The function contains an if/else statement that

controls the repetition. - As long as the times argument is greater than

zero, it will display the message and call itself

again. Each time it calls itself, it passes times

- 1 as the argument.

Recursion

- For example, let's say a program calls the

function with the following statement - Message(5)
- The argument, 5, will cause the function to call

itself 5 times. The first time the function is

called, the if statement will display the message

and then call itself with 4 as the argument.

Figure 19-1 (on the next slide) illustrates this.

Figure 19-1

Each time the function is called, a new instance

of the times parameter is created.

In the first call to the function,times is set

to 5.

1st call of the function

Value of times 5

When the function callsitself, a new instance

oftimes is created with thevalue 4.

2nd call of the function

Value of times 4

Figure 19-1

1st call of the function

Value of times 5

This cycle repeats itselfuntil 0 is passed to to

thefunction.

2nd call of the function

Value of times 4

3rd call of the function

Value of times 3

4th call of the function

Value of times 2

5th call of the function

Value of times 1

Depth of recursion 6

6th call of the function

Value of times 0

Program 19-1

// This program demonstrates a simple recursive

function.include ltiostream.hgt// Function

prototypevoid message(int)void

main(void) message(5)

Program 19-1 (continued)

//

// Definition of function Message. If

the value in times is // greater than 0, the

message is displayed and the //

function is recursively called with the argument

// times - 1.

//

void

message(int times) if (times gt 0) cout ltlt

"This is a recursive function.\n" message(times

- 1) return

Program 19-1 (continued)

Program Output This is a recursive

function. This is a recursive function. This is

a recursive function. This is a recursive

function. This is a recursive function.

Program 19-2

// This program demonstrates a simple recursive

function.include ltiostream.hgt// Function

prototypevoid message(int)void

main(void) message(5)

Program 19-2 (continued)

//

// Definition of function Message. If

the value in times is // greater than 0, the

message is displayed and the //

function is recursively called with the argument

// times - 1.

//

void

message(int times) cout ltlt "Message called

with " ltlt times ltlt " in times.\n" if (times gt

0) cout ltlt "This is a recursive

function.\n" message(times - 1) cout ltlt

"Message returning with " ltlt times cout ltlt " in

times.\n"

Program 19-2 (continued)

Program Output Message called with 5 in

Times. This is a recursive function. Message

called with 4 in Times. This is a recursive

function. Message called with 3 in Times. This

is a recursive function. Message called with 2

in Times. This is a recursive function. Message

called with 1 in Times. This is a recursive

function. Message called with 0 in

Times. Message returning with 0 in

Times. Message returning with 1 in

Times. Message returning with 2 in

Times. Message returning with 3 in

Times. Message returning with 4 in

Times. Message returning with 5 in Times.

Recursion

- The role of recursive functions in programming is

to break complex problems down to a solvable

problem. - The solvable problem is known as the base case.
- A recursive function is designed to terminate

when it reaches its base case.

The numChars function

int numChars(char search, char str, int

subscript) if (strsubscript '\0')

return 0 else if (strsubscript

search) return 1 numChars(search, str,

subscript1) else return numChars(search,

str, subscript1)

- The function's parameters are
- search The character to be searched for and

counted. - str An array containing the string to be

searched. - subscript The starting subscript for the search.

The numChars function

The first if statement determines if the end of

the string has been reached if (strsubscript

'\0') If so, the function returns 0,

indicating there are no more characters to count.

Otherwise, the following if/else statement is

executed if (strsubscript search)

return 1 numChars(search, str, subscript1)

else return numChars(search, str,

subscript1)If strsubscript contains the

search character, the function performs a

recursive call. The return statement returns 1

the number of times the search character appears

in the string, starting at subscript 1. If

strsubscript does not contain the search

character, a recursive call is made to search the

remainder of the string.

Program 19-3

// This program demonstrates a recursive function

for// counting the number of times a character

appears// in a string.include

ltiostream.hgtint numChars(char, char ,

int)void main(void) char array

"abcddddef" cout ltlt "The letter d appears

ltlt numChars('d', array, 0) ltlt " times\n"

Program 19-3 (continued)

//

// Function numChars. This recursive function

// counts the number of times the character

// search appears in the string str. The

search // begins at the subscript stored in

subscript. //

int numChars(char search, char

str, int subscript) if (strsubscript

'\0') return 0 else if (strsubscript

search) return 1 numChars(search, str,

subscript1) else return numChars(search,

str, subscript1)

Program 19-3 (continued)

Program Output The letter d appears 4 times.

Direct and Indirect Recursion

- These examples show recursive functions that

directly call themselves. This is known as direct

recursion. - There is also the possibility of creating

indirect recursion in a program. This occurs when

function A calls function B, which in turn calls

function A.

19.2 The Recursive Factorial Function

In mathematics, the notation n! represents the

factorial of the number n. The factorial of a

number is defined as n! 1 2 3 ...

n if n gt 0 1 if n 0

The Recursive Factorial Function

Another way of defining the factorial of a

number, using recursion, is Factorial(n) n

Factorial(n - 1) if n gt 0 1 if n

0 The following C function implements the

recursive definition shown above int

factorial(int num) if (num gt 0) return num

factorial(num - 1) else return 1

Program 19-4

// This program demonstrates a recursive function

to // calculate the factorial of a

number.include ltiostream.hgt// Function

prototypeint factorial(int)void

main(void) int number cout ltlt "Enter an

integer value and I will display\n" cout ltlt

"its factorial " cin gtgt number cout ltlt "The

factorial of " ltlt number ltlt " is " cout ltlt

factorial(number) ltlt endl

Program 19-4

//

// Definition of factorial. A

recursive function to calculate // the

factorial of the parameter, num.

//

int factorial(int

num) if (num gt 0) return num factorial(num

- 1) else return 1

Program 19-4

Program Output with Example Input Enter an

integer value and I will displayits factorial

4The factorial of 4 is 24

19.3 The Recursive gcd Function

Our next example of recursion is the calculation

of the greatest common divisor, or GCD, of two

numbers. Using Euclid's Algorithm, the GCD of two

positive integers, x and y, is GCD(x, y) y

if y divides x evenly GCD(y,

remainder of y/x) The definition above states

that the GCD of x and y is y if x/y has no

remainder. Otherwise, the answer is the GCD of y

and the remainder of x/y. This is demonstrated

in Program 19-5.

Program 19-5

// This program demonstrates a recursive function

to calculate// the greatest common divisor (gcd)

of two numbers.include ltiostream.hgt//

Function prototypeint gcd(int, int)void

main(void) int num1, num2 cout ltlt "Enter

two integers " cin gtgt num1 gtgt num2 cout ltlt

"The greatest common divisor of " ltlt num1 cout

ltlt " and " ltlt num2 ltlt " is " cout ltlt gcd(num1,

num2) ltlt endl

Program 19-5

//

// Definition of gcd. This function

uses recursion to // calculate the greatest

common divisor of two integers, // passed into

the parameters x and y.

//

int gcd(int x, int y) if (x y

0) return y else return gcd(y, x

y) Program Output with Example Input Enter

two integers 49 28 The greatest common divisor

of 49 and 28 is 7

19.4 Solving Recursively Defined Problems

- Some mathematical problems are designed to be

solved recursively. One example is the

calculation of Fibonacci numbers, which are the

following sequence - 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,

233,

Solving Recursively Defined Problems

- The Fibonacci series can be defined as
- F0 0,
- F1 1,
- FN FN-1 FN-2 for N ? 2.

Solving Recursively Defined Problems

- A recursive C function to calculate the nth

number in the Fibonacci series is shown below .

int fib(int n) if (n lt 0) return 0 else

if (n 1) return 1 else return fib(n - 1)

fib(n - 2)

Program 19-6

// This programs demonstrates a recursive

function// that calculates Fibonacci

numbers.include ltiostream.hgt// Function

prototypeint fib(int)void main(void) cout

ltlt "The first 10 Fibonacci numbers are\n" for

(int x 0 x lt 10 x) cout ltlt fib(x) ltlt "

" cout ltlt endl

Program 19-6 (continued)

////

Function fib. Accepts an int argument // in n.

This function returns the nth // Fibonacci

number. //

int fib(int n) if (n

lt 0) return 0 else if (n 1) return

1 else return fib(n - 1) fib(n - 2)

Program 19-6 (continued)

Program Output The first 10 Fibonacci numbers

are0 1 1 2 3 5 8 13 21 34

19.5 Recursive Linked List Operations

- Recursion may be used in some operations on

linked lists. - We will look at functions that
- Count the number of nodes in a list, and
- Display the value of the list nodes in reverse

order. - We will use the FloatList class developed in

Chapter 17.

Counting the Nodes in the List

int FloatListcountNodes(ListNode

nodePtr) if (nodePtr ! NULL) return 1

countNodes(nodePtr-gtnext) else return 0

The base case for the function is nodePtr being

equal to NULL.

Counting the Nodes in the List

The function's recursive logic can be expressed

as If the current node has a value Return

1 the number of the remaining

nodes. Else Return 0. end If.

Program 19-7

include ltiostream.hgtinclude "FloatList2.hvoi

d main(void) FloatList list for (int x 0

x lt 10 x) list.insertNode(x) cout ltlt "The

number of nodes is ltlt list.numNodes() ltlt

endl Program Output The number of nodes is 10

Displaying the List Nodes in Reverse Order

void FloatListshowReverse(ListNode

nodePtr) if (nodePtr ! NULL) showReverse

(nodePtr-gtnext) cout ltlt nodePtr-gtvalue ltlt "

"

The base case for the function is nodePtr being

equal to NULL.

Program 19-8

// This program demonstrates the FloatList

class's// recursive function for displaying the

list's nodes// in reverse.include

ltiostream.hgtinclude "FloatList2.hvoid

main(void) FloatList list for (float x

1.5 x lt 15 x 1.1) list.appendNode(x) cout

ltlt "Here are the values in the

list\n" list.displayList() cout ltlt "Here

are the values in reverse order\n" list.display

Backwards()

Program 19-8 (continued)

Program OutputHere are the values in the

list1.52.63.74.85.978.19.210.311.412.5

13.614.7Here are the values in reverse

order14.7 13.6 12.5 11.4 10.3 9.2 8.1 7 5.9 4.8

3.7 2.6 1.5

19.6 A Recursive Binary Search Function

- The binary search algorithm, which you learned

about in Chapter 8, can be implemented

recursively. For example, the procedure can be

expressed as - If arraymiddle equals the search value, then

the value is found. - Else, if arraymiddle is less than the search

value, perform a binary search on the upper half

of the array. - Else, if arraymiddle is greater than the search

value, perform a binary search on the lower half

of the array.

A Recursive Binary Search Function

- A recursive binary search function is shown

below. int binarySearch(int array, int first,

int last, int value) int middle // Mid

point of search if (first gt last) return

-1 middle (first last) / 2 if

(arraymiddle value) return middle if

(arraymiddle lt value) return

binarySearch(array, middle1,last,value)

else return binarySearch(array,

first,middle-1,value)

A Recursive Binary Search Function

- int binarySearch(int array, int first, int

last, int value) - The 1st parameter, array, is the array to be

searched. - The 2nd parameter, first, holds the subscript of

the first element in the search range (the

portion of the array to be searched). - The 3rd parameter, last, holds the subscript of

the last element in the search range. - The 4th parameter, value, holds the value to be

searched for. - This function returns the subscript of the value

if it is found, or -1 if the value is not found.

Program 19-9

// This program demonstrates the recursive

binarySearch function, which// performs a binary

search on an integer array.include

ltiostream.hgt// Function prototypeint

binarySearch(int , int, int, int)const int

arrSize 20void main(void) int

testsarrSize 101, 142, 147, 189, 199, 207,

222, 234, 289, 296, 310,

319, 388, 394, 417, 429,

447, 521, 536, 600 int results, empID cout

ltlt "Enter the Employee ID you wish to search for

" cin gtgt empID

Program 19-9 (continued)

results binarySearch(tests, 0, arrSize - 1,

empID) if (results -1) cout ltlt "That

number does not exist in the array.\n" else

cout ltlt "That ID is found at element " ltlt

results cout ltlt " in the array\n" //

// The binarySearch function performs a

recursive binary search // on a range of

elements of an integer array passed into the

// parameter array.The parameter first holds

the subscript of // the range's starting

element, and last holds the subscript // of

the ranges's last element. The paramter value

holds the // the search value. If the search

value is found, its array // subscript is

returned. Otherwise, -1 is returned indicating

// the value was not in the array.

//

Program 19-9

int binarySearch(int array, int first, int

last, int value) int middle // Mid point

of search if (first gt last) return -1

middle (first last)/2 if

(arraymiddlevalue) return middle if

(arraymiddleltvalue) return

binarySearch(array, middle1,last,value)

else return binarySearch(array,

first,middle-1,value) Program Output with

Example Input Shown in Bold Enter the Employee

ID you wish to search for 521 EnterThat ID is

found at element 17 in the array

The QuickSort Algorithm

- Can be used to sort lists stored in arrays or

linear linked lists. It sorts a list by dividing

it into two sublists. Between the sublists is a

selected value known as the pivot. This is

illustrated in Figure 19-4.

The QuickSort Algorithm

- Once a pivot value has been selected, the

algorithm exchanges the other values in the list

until all the elements in sublist 1 are less than

the pivot, and all the elements in sublist 2 are

greater than the pivot. - Once this is done, the algorithm repeats the

procedure on sublist 1, and then on sublist 2.

The recursion stops when there is only one

element in a sublist. At that point the original

list is completely sorted.

The QuickSort Algorithm

- The algorithm is coded primarily in two

functions QuickSort and Partition. QuickSort is

a recursive function. Its pseudocode is shown

below.

QuickSort If Starting Index lt Ending

Index Partition the List around a

Pivot. QuickSort Sublist 1. QuickSort Sublist

2. end If.

The QuickSort Algorithm

The C Code void quickSort(int set, int

start, int end) int pivotPoint if (start lt

end) // Get the pivot point. pivotPoint

partition(set, start, end) // Sort the first

sub list. quickSort(set, start, pivotPoint -

1) // Sort the second sub list. quickSort(set

, pivotPoint 1, end)

The QuickSort Algorithm

The partition Functionint partition(int set,

int start, int end) int pivotValue,

pivotIndex, mid mid (start end) /

2 exchange(setstart, setmid) pivotIndex

start pivotValue setstart for (int scan

start 1 scan lt end scan) if

(setscan lt pivotValue) pivotIndex e

xchange(setpivotIndex, setscan) excha

nge(setstart, setpivotIndex) return

pivotIndex

The QuickSort Algorithm

The exchange Functionvoid exchange(int

value1, int value2) int temp

value1 value1 value2 value2 temp

Program 19-10

// This program demonstrates the QuickSort

Algorithminclude ltiostream.hgt// Function

prototypesvoid quickSort(int , int, int)int

partition(int , int, int)void exchange(int ,

int )void main(void) int array10 7,

3, 9, 2, 0, 1, 8, 4, 6, 5 int x //

Counter for (x 0 x lt 10 x) cout ltlt

arrayx ltlt " " cout ltlt endl quickSort(array,

0, 9) for (x 0 x lt 10 x) cout ltlt

arrayx ltlt " " cout ltlt endl The code for

the remainder of the program was previously shown

Program 19-10

Program Output 7 3 9 2 0 1 8 4 6 50 1 2 3 4 5 6

7 8 9

19.8 Exhaustive Algorithms

- An exhaustive algorithm is one that finds a best

combination of items by looking at all the

possible combinations.

Exhaustive Algorithms

- For example, consider all the different ways you

canmake change for 1.00 using our system of

coins - 1 dollar piece, or2 fifty-cent pieces, or
- 4 quarters, or
- 1 fifty-cent piece and 2 quarters, or
- 3 quarters, 2 dimes, and 1 nickel, or
- there are many more possibilities.

Exhaustive Algorithms

- Although there are many ways to make change for

1.00, some ways are better than others. For

example, you would probably rather give a single

dollar piece instead of 100 pennies. - An algorithm that looks at all the possible

combinations of items in order to find the best

combination of items is called an exhaustive

algorithm.

Program 19-11

// This program demonstrates a recursive function

that exhaustively// searches through all

possible combinations of coin values to find//

the best way to make change for a specified

amount.include ltiostream.hgt// Constantsconst

int maxCoinsChange 100 // Maximum number of

coins to give in changeconst int maxCoinValues

6 // Maximum number of coin valuesconst int

noSolution 1000000 // Indicates no

solution// Function prototypevoid

makeChange(int, int, int, int)// coinValues

- global array of coin values to choose fromint

coinValuesmaxCoinValues 100, 50, 25, 10, 5,

1 // bestCoins - global array of best coins

to make change withint bestCoinsmaxCoinsChange

// Global variablesint numBestCoins

noSolution, // Number of coins in bestCoins

numSolutions 0, // Number of ways to make

change numCoins // Number of allowable

coins

Program 19-11 (continued)

void main(void) int coinsUsedmaxCoinsChange,

// List of coins used numCoinsUsed 0, //

The number coins used amount // The

amount to make change for // Display the

possible coin values. cout ltlt "Here are the

valid coin values, in cents " for (int index

0 index lt 5 index) cout ltlt

coinValuesindex ltlt " " cout ltlt endl // Get

input from the user. cout ltlt "Enter the amount

of cents (as an integer) to make change for

" cin gtgt amount cout ltlt "What is the maximum

number of coins to give as change? " cin gtgt

numCoins // Call the recursive

function. makeChange(numCoins, amount,

coinsUsed, numCoinsUsed)

Program 19-11 (continued)

// Display the results. cout ltlt "Number of

possible combinations " ltlt numSolutions ltlt

endl cout ltlt "Best combination of

coins\n" if (numBestCoins

noSolution) cout ltlt "\tNo solution\n" else

for (int count 0 count lt numBestCoins

count) cout ltlt bestCoinscount ltlt "

" cout ltlt endl//

//

Function makeChange. This function uses the

following parameters // coinsLeft - The

number of coins left to choose from.

// amount - The amount to make change for.

// coinsUsed - An

array that contains the coin values used so far.

// numCoinsUsed - The number of values in

the coinsUsed array. //

// This recursive function finds all the

possible ways to make change // for the value

in amount. The best combination of coins is

stored in // the array bestCoins.

//

Program 19-11

void makeChange(int coinsLeft, int amount, int

coinsUsed, int numCoinsUsed) int coinPos, //

To calculate array position of coin being used

count // Loop counter if (coinsLeft

0) // If no more coins are left return else

if (amount lt 0) // If amount to make change for

is negative return else if (amount 0) //

If solution is found // Store as bestCoins

if best if (numCoinsUsed lt numBestCoins)

for (count 0 count lt numCoinsUsed

count) bestCoinscount

coinsUsedcount numBestCoins

numCoinsUsed numSolutions return

Program 19-11

// Find the other combinations using the

coin coinPos numCoins - coinsLeft coinsUsedn

umCoinsUsed coinValuescoinPos numCoinsUsed

makeChange(coinsLeft, amount -

coinValuescoinPos, coinsUsed,

numCoinsUsed) // Find the other combinations

not using the coin numCoinsUsed-- makeChange(co

insLeft - 1, amount, coinsUsed,

numCoinsUsed) Program Output with Example

Input Shown in Bold Here are the valid coin

values, in cents 100 50 25 10 5Enter the amount

of cents (as an integer) to make change for 62

EnterWhat is the maximum number of coins to

give as change? 6 EnterNumber of possible

combinations 77Best combination of coins50 10

1 1