0% found this document useful (0 votes)
8 views

Lecture 07 - Recursion

Uploaded by

caokhuong12311
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Lecture 07 - Recursion

Uploaded by

caokhuong12311
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 70

Vietnam National University of HCMC

International University
School of Computer Science and Engineering

Data Structures and Algorithms


★ Recursion ★

Dr Vi Chi Thanh - [email protected]


https://vichithanh.github.io
Week by week topics (*)

1. Overview, DSA, OOP and Java 7. Advanced Sorting


2. Arrays 8. Binary Tree
3. Sorting 9. Hash Table
4. Queue, Stack 10.Graphs
5. List 11.Graphs Adv.
6. Recursion Final-Exam
Mid-Term 10 LABS

T UE SD AY , 2 2 O CT O BE R 2 0 24 2
Objectives

1. Introduction 8. Tower of Hanoi


2. Triangular Numbers 9. Merge sort
3. Recursive definition 10.Tail recursion
4. Recursive characteristics 11.Non-tail recursion
5. Factorials
12.Indirect recursion
6. Recursion implementation &
13.Nested recursion
Stacks
7. Recursive binary search 14.Excessive recursion

T UE SD AY , O CT O BE R 2 2 , 2 02 4 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 3
T UE SD AY , 2 2 O CT O BE R 2 0 24 4
Triangle Numbers: Examples

T UE SD AY , 2 2 O CT O BE R 2 0 24 5
Finding nth
Term using
a Loop

T UE SD AY , O CT O BE R 2 2 , 2 02 4 6
T UE SD AY , 2 2 O CT O BE R 2 0 24 7
Finding nth Term using Recursion
• Value of the nth term is the SUM of:
• The first column (row): n
• The SUM of the rest columns (rows)

T UE SD AY , 2 2 O CT O BE R 2 0 24 8
Recursive method

T UE SD AY , 2 2 O CT O BE R 2 0 24 9
Recursive method

• Now, it is complete with stopping condition

• See triangle.java program

T UE SD AY , 2 2 O CT O BE R 2 0 24 10
Definition

▪ When a function calls itself, this is known as recursion.


▪ Is a way to archive repetition, such as while-loop and for-loop
▪ This is an important theme in Computer Science that crops up time &
time again.
▪ Can sometimes lead to very simple and elegant programs.

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 11
Characteristics of Recursive Program/ Algorithms

▪ There are three basic rules for developing recursive algorithms.


▪ Know how to take one step.
▪ Break each problem down into one step plus a smaller problem.
▪ Know how and when to stop.
▪ Example for recursive program: public class FactorialCalculator {

▪ Factorial of a natural number public static int factorial(int n) {


if (n < 0) {
throw new IllegalArgumentException("Factorial is not
defined for negative numbers.");
} else if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
}

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 12
Recursion Characteristics

• There is some version of the problem that is simple enough that the
routine can solve it, and return, without calling itself
• Is recursion efficient?
• No
• Address of calling methods must be remembered (in stack)
• Intermediate arguments must also be stored

T UE SD AY , 2 2 O CT O BE R 2 0 24 13
Example: Factorials

T UE SD AY , 2 2 O CT O BE R 2 0 24 14
Computing factorial by simple iteration

• See Factorial1.java

T UE SD AY , 2 2 O CT O BE R 2 0 24 15
Factorials

T UE SD AY , 2 2 O CT O BE R 2 0 24 16
Computing factorial by recursion

• See Factorial2.java
• Computing factorial by simulating recursion using a stack
• Factorial3.java

T UE SD AY , 2 2 O CT O BE R 2 0 24 17
Recursion & stack

• Recursion is usually implemented by stacks

T UE SD AY , 2 2 O CT O BE R 2 0 24 18
Method calls and recursion implementation

• Each time a method is called, an activation record (AR) is allocated for it in


the memory. A recursive function that calls itself times N must allocate N
activation records.
• This record usually contains the following information:
• Parameters and local variables used in the called method.
• A dynamic link, which is a pointer to the caller's activation record.
• Return address to resume control by the caller, the address of the caller’s instruction
immediately following the call.
• Return value for a method not declared as void. Because the size of the activation
record may vary from one call to another, the returned value is placed right above
the activation record of the caller.

T UE SD AY , 2 2 O CT O BE R 2 0 24 19
Method calls and recursion implementation

• Each new activation record is placed on the top of the run-time stack
• When a method terminates, its activation record is removed from the
top of the run-time stack
• Thus, the first AR placed onto the stack is the last one removed.

T UE SD AY , 2 2 O CT O BE R 2 0 24 20
TUESDAY , OCTOBER 22 ,
202 4 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 21
Anatomy of a recursive call

• Example: Factorial of a number

T UE SD AY , 2 2 O CT O BE R 2 0 24 22
Binary Search: Recursion vs. Loop

T UE SD AY , 2 2 O CT O BE R 2 0 24 23
Binary Search: Recursion vs.
Loop

T UE SD AY , 2 2 O CT O BE R 2 0 24 24
Recursive binary search implementation

• BinarySearchApp.java
• Trace the recursion by printing lowerBound and upperBound at each
call and exit

T UE SD AY , 2 2 O CT O BE R 2 0 24 25
Divide-and-conquer

• Divide problems into two smaller problems


• Solve each one separately (divide again)
• Usually have 2 recursive calls in main method: one for each half
• Can be non-recursive
• Examples
• The Towers of Hanoi
• MergeSort

T UE SD AY , 2 2 O CT O BE R 2 0 24 26
Towers of Hanoi

• An ancient puzzle consisting of a number of


disks placed on three columns (A, B, C)
• Objectives
• Transfer all disks from column A to column C
• Rules
• Only one disk can be moved at a time
• No disk can be placed on a disk that is smaller
than itself

T UE SD AY , 2 2 O CT O BE R 2 0 24 27
Algorithm

• Move first n-1 subtree from S to I


• Move the largest disk from S to D
• Move the subtree from I to D
T UE SD AY , 2 2 O CT O BE R 2 0 24 28
Algorithm

T UE SD AY , 2 2 O CT O BE R 2 0 24 29
Implementation

T UE SD AY , 2 2 O CT O BE R 2 0 24 30
Implementation

• TowersApp.java
• Include a counter and print the number of recursive steps for
different number of disks

T UE SD AY , 2 2 O CT O BE R 2 0 24 31
Classification of recursive functions by number
of recursive calls
▪ Considering the maximum number of recursive calls that may be
started from within the body of a single activation:
▪ Linear recursion: Only 1 recursive call (to itself) inside the recursive
function (e.g., binary search, factorial).
▪ Binary recursion: There exactly 2 recursive calls (to itself) inside the
recursive function (e.g., Fibonacci number) .
▪ Multiple recursion: There are 3 or more recursive calls (to itself)
inside the recursive function (e.g., "Sierpinski triangle").
T UE SD AY , 2 2 O CT O BE R 2 0 24 32
Tail recursion

• A recursion is a tail recursion if:


• Any recursive call that is made from one context is the very last operation in
that context,
• with the return value of the recursive call (if any) immediately returned by the
enclosing recursion. public class FactorialCalculator {

public static int factorial(int n) { public static int factorial(int n) {


return factorialHelper(n, 1); if (n < 0) {
} throw new IllegalArgumentException("Factorial is not
defined for negative numbers.");
private static int factorialHelper(int n, int result) { } else if (n == 0) {
if (n == 0) { return 1;
return result; } else {
} else { return n * factorial(n - 1);
return factorialHelper(n - 1, result * n); }
} }
} }

T UE SD AY , 2 2 O CT O BE R 2 0 24 33
Indirect recursion
public class IndirectRecursionExample {
▪ If f() calls itself, it is direct public static void functionA(int n) {

recursive
if (n > 0) {
System.out.print(n + " ");
functionB(n - 1);
}
▪ If f() calls g(), and g() calls f(). It is }

public static void functionB(int n) {


indirect recursion. The chain of if (n > 0) {
System.out.print(n + " ");

intermediate calls can be of an


functionA(n - 1);
}
}

arbitrary length, as in: public static void main(String[] args) {


int n = 5;
System.out.print("Indirect Recursion Output: ");
f() ➔ f1() ➔ f2() ➔ ... ➔ fn() ➔ f() }
functionA(n);

Indirect Recursion Output: 5 4 3 2 1 1 2 3 4 5

T UE SD AY , 2 2 O CT O BE R 2 0 24 34
Nested recursion

▪ A function is not only defined in terms of itself but also is used as one
of the parameters
▪ Examples: Ackermann function
▪ A(0, y) = y + 1
▪ A(x, 0) = A(x - 1, 1)
▪ A(x, y) = A(x - 1, A(x, y - 1))
This function is interesting because of its value
grows rapidly, even for small inputs.
A(3,1) = 24 - 3
A(4,1) = 265536 - 3
T UE SD AY , 2 2 O CT O BE R 2 0 24 35
Eliminate recursion

• Some algorithms are naturally in recursive form (merge sort, Hanoi


Tower, etc.)
• But recursion is not efficient
→ try to transform to non-recursive approach

T UE SD AY , 2 2 O CT O BE R 2 0 24 36
Example: Fibonacci sequence

▪ A well-known example of a recursive function is the Fibonacci


sequence.
▪ The first term is 0, the second term is 1 and each successive term is
defined to be the sum of the two previous terms, i.e. :
▪ fib(0) is 0
▪ fib(1) is 1
▪ fib(2) is 1
▪ fib(n) is fib(n-1) + fib(n-2)
▪ 0, 1, 1, 2, 3, 5, 8, 13, 21, ...

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 37
1. public class FibonacciSequence {
Example: Fibonacci
2.

3.
public static int fibonacci(int n) {

if (n <= 0) {
sequence
4. return 0; Execution:
5. } else if (n == 1) {

6. return 1;
fibonacci(0): 0
7. } else {
fibonacci(1): 1
8. return fibonacci(n - 1) + fibonacci(n - 2);
fibonacci(2): 1
9. }

10. }
fibonacci(3): 2

11. public static void main(String[] args) { fibonacci(4): 3


12. int n = 10; fibonacci(5): 5
13. for (int i = 0; i <= n; i++) {
fibonacci(6): 8
14. System.out.print("fibonacci(" + i + "): " +
fibonacci(i) + "\n"); fibonacci(7): 13

15. } fibonacci(8): 21
16. } fibonacci(9): 34
17. }
fibonacci(10): 55

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 38
Excessive recursion

• Some recursive methods repeats the computations for some parameters, which
results in long computation time even for simple cases.
• For example, consider the Fibonacci sequence.
• In Java it can be implemented recursively as:

1 /** Returns the nth Fibonacci number (inefficiently). */


2 public static long fibonacciBad(int n) {
3 if (n <= 1)
This implementation looks
4 return n;
5 else very natural but extremely
6 return fibonacciBad(n−2) + fibonacciBad(n−1); inefficient! (O(2^n))
7 }

T UE SD AY , 2 2 O CT O BE R 2 0 24 39
Excessive recursion
The tree of calls for fibo(4)

T UE SD AY , 2 2 O CT O BE R 2 0 24 40
Excessive recursion

• Better Fibonacci implementation: define a recursive method that


• returns an array with
• two consecutive Fibonacci numbers {Fn, Fn−1}
• using the convention F−1 = 0.
1 /** Returns array containing the pair of Fibonacci numbers, F(n) and F(n−1). */
2 public static long[ ] fibonacciGood(int n) {
3 if (n <= 1) {
4 long[ ] answer = {n, 0};
5 return answer;
6 } else {
7 long[ ] temp = fibonacciGood(n − 1); // returns {Fn−1, Fn−2}
8 long[ ] answer = {temp[0] + temp[1], temp[0]}; // we want {Fn, Fn−1}
9 return answer;
10 }
11 }
T UE SD AY , 2 2 O CT O BE R 2 0 24 41
More Examples – Drawing fractals

• Inspired by the growth patterns of


natural trees.
• Each branch of a fractal tree is
divided into smaller branches
• Smaller branches are divided into
even smaller branches, and so on, Fractal Tree
creating a recursive structure.

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 42
More Examples – Drawing fractals

• Starts as a basic geometric shape,


often a line or an arc
• Then applying a series of scaling and
rotation operations to create smaller
copies
• These smaller copies are positioned in
a specific arrangement (often Fractal Spiral
following a spiral-like pattern)
• The process is repeated at smaller and
smaller scales.

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 43
More Examples – Von Knoch snowflakes

• Divide an interval side into


three even parts
• Move one-third of side in the
direction specified by angle

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 44
More Examples – Sierpinski Triangle

• A fractal attractive fixed set


• The overall shape of an equilateral
triangle
• Subdivided recursively into
smaller equilateral triangles

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 45
Recursion vs. Iteration

• Some recursive algorithms can also be easily implemented with


loops
• When possible, it is usually better to use iteration, since we don’t
have the overhead of the run-time stack (as in the previous slide)
• Other recursive algorithms are very difficult to do any other way

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 46
Merge Sort

T UE SD AY , 2 2 O CT O BE R 2 0 24 47
Merge Sort

• Simple Sorting Algorithms: O(N2)


• Bubble Sort, Selection Sort, Insertion Sort
• Using Sorted Linked List
• MergeSort: O(NlogN)
• Approach to MergeSort
• Merging Two Sorted Arrays
• Sorting by Merging
• Efficiency of MergeSort

T UE SD AY , 2 2 O CT O BE R 2 0 24 48
Merging two sorted
arrays
• Given two sorted arrays (A, B)
• Creating sorted array C
containing all elements of A, B

T UE SD AY , 2 2 O CT O BE R 2 0 24 49
Merge Sort

• Divide an array in halves


• Sort each half: Using recursion
• Divide half into quarters
• Sort each of the quarters
• Merge them to make a sorted half
• Call merge() to merge two halves into a
single sorted array

T UE SD AY , 2 2 O CT O BE R 2 0 24 50
Merge Sort

• Divide an array in halves


• Sort each half: Using recursion
• Divide half into quarters
• Sort each of the quarters
• Merge them to make a sorted half
• Call merge() to merge two halves into a
single sorted array

T UE SD AY , 2 2 O CT O BE R 2 0 24 51
Merge Sort
• Array size not a power of 2

T UE SD AY , 2 2 O CT O BE R 2 0 24 52
Merge sort - algorithm

• The merge sort algorithm is defined recursively:


• If the list is of size 1, it is sorted—we are done;
• Otherwise:
• Divide an unsorted list into two sub-lists,
• Sort each sub-list recursively using merge sort, and
• Merge the two sorted sub-lists into a single sorted list

➔ This is the first divide-and-conquer algorithm

T UE SD AY , 2 2 O CT O BE R 2 0 24 53
Implementation

T UE SD AY , 2 2 O CT O BE R 2 0 24 54
Merge sort – Merging Example

• Consider the two sorted arrays and an empty array


• Define three indices at the start of each array
Merging Example

• We compare 2 and 3: 2 < 3


• Copy 2 down
• Increment the corresponding indices
Merging Example

• We compare 3 and 7
• Copy 3 down
• Increment the corresponding indices
Merging Example

• We compare 5 and 7
• Copy 5 down
• Increment the appropriate indices
Merging Example

• We compare 18 and 7
• Copy 7 down
• Increment...
Merging Example

• We compare 18 and 12
• Copy 12 down
• Increment...
Merging Example

• We compare 18 and 16
• Copy 16 down
• Increment...
Merging Example

• We compare 18 and 33
• Copy 18 down
• Increment...
Merging Example

• We compare 21 and 33
• Copy 21 down
• Increment...
Merging Example

• We compare 24 and 33
• Copy 24 down
• Increment...
Merging Example

• We would continue until we have passed


beyond the limit of one of the two arrays

• After this, we simply copy over all


remaining entries in the non-
empty array
Code
Implementation

T UE SD AY , 2 2 O CT O BE R 2 0 24 66
Implementation

• MergeSortApp.java
• Modify the code to print out the output after each recursive step
• Count the number of recursive calls. Estimate the relationship
between the number of calls and the number of elements.

T UE SD AY , 2 2 O CT O BE R 2 0 24 67
Efficiency of Merge
Sort: O(NlogN)

T UE SD AY , 2 2 O CT O BE R 2 0 24 68
Summary

• Recursive definitions are programming concepts that define themselves


• Some value of its arguments causes a recursive method to return without
calling itself. This is called the base case.
• Recursive definitions serve two purposes:
• Generating new elements
• Testing whether an element belongs to a set
• Recursive definitions are frequently used to define functions and
sequences of numbers
• Tail recursion is characterized using only one recursive call at the very end
of a method implementation.

T UE SD AY , 2 2 O CT O BE R 2 0 24 D A TA ST R U C T U R E S A N D A L G O RI T H M S IN JA V A 69
Vietnam National University of HCMC
International University
School of Computer Science and Engineering

THANK YOU

Dr Vi Chi Thanh - [email protected]


https://vichithanh.github.io

You might also like