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

Type of Recursion

This document describes 6 different types of recursion: 1. Linear recursion which calls itself once each run like a factorial function. 2. Tail recursion where the recursive call is the last thing done like calculating GCD. 3. Binary recursion which has two or more recursive calls like mathematical combinations. 4. Exponential recursion which has an exponential number of calls related to data set size, like permutations. 5. Nested recursion where a function is recursively called as an argument like Ackermann's function. 6. Mutual recursion where functions recursively call each other in a cycle like determining even/odd numbers. Code examples are provided for each type.

Uploaded by

Yuyun Joe
Copyright
© © All Rights Reserved
0% found this document useful (0 votes)
58 views

Type of Recursion

This document describes 6 different types of recursion: 1. Linear recursion which calls itself once each run like a factorial function. 2. Tail recursion where the recursive call is the last thing done like calculating GCD. 3. Binary recursion which has two or more recursive calls like mathematical combinations. 4. Exponential recursion which has an exponential number of calls related to data set size, like permutations. 5. Nested recursion where a function is recursively called as an argument like Ackermann's function. 6. Mutual recursion where functions recursively call each other in a cycle like determining even/odd numbers. Code examples are provided for each type.

Uploaded by

Yuyun Joe
Copyright
© © All Rights Reserved
You are on page 1/ 23

Dwi Putri Wahyuningsih

2019390004

Assignment - 2: Type of Recursion

Write all type of recursive methods (about 20 methods), describe each of them using your own
word, and give a brief code example.

1. Linear Recursive
A linear recursive function is one that only makes one call to itself each time the function
is run (as opposed to a function that calls itself multiple times during its execution).
Factorial functions are good examples of linear recursion.
Code:
import java.util.Scanner;

public class Factorial {

public static void main(String[] args)


{
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the number whose factorial
is to be found: ");
int n = scanner.nextInt();
int result = factorial(n);
System.out.println("The factorial of " + n + " is
" + result);
}

public static int factorial(int n)


{
int result = 1;
for (int i = 1; i <= n; i++)
{
result = result * i;
}

return result;
}
}
Result

2. Tail recursive
Tail recursion is a form of linear recursion. In tail recursion, the recursive call is the last
thing the function does. Often, recursive call values are returned. A great example of a
tail-recursive function is a function for calculating the GCD, or Largest Common
Denominator, from two numbers:
int gcd (int m, int n) {int r; if (m <n) return gcd (n, m); r = m% n; if (r == 0) returns (n);
else return (gcd (n, r));}
Code:
import java.util.Scanner;
public class GCDExample1 {

public static void main(String[] args) {

int num1, num2;

//Reading the input numbers


Scanner scanner = new Scanner(System.in);
System.out.print("Enter first number:");
num1 = (int)scanner.nextInt();
System.out.print("Enter second number:");
num2 = (int)scanner.nextInt();

//closing the scanner to avoid memory leaks


scanner.close();
while (num1 != num2) {
if(num1 > num2)
num1 = num1 - num2;
else
num2 = num2 - num1;
}

//displaying the result


System.out.printf("GCD of given numbers is: %d",
num2);
System.out.println ("");
}

}
Result

3. Binary Recursive
Some recursive functions do not just have one call, they have two (or more). A function
with two recursive calls is called a binary recursive function. Mathematical combination
operations are a great example of a function that can be quickly implemented as a
recursive binary function. The number of combinations, often represented as nCk where
we select n elements from a set of k elements, can be implemented as follows:
int select (int n, int k) {if (k == 0 || n == k) return (1); else return (select (n-1, k) + select
(n-1, k-1));}
Code:
class BinarySearch {

// Returns index of x if it is present


// in arr[l..r], else return -1
int binarySearch(int arr[], int l,
int r, int x)
{
//Restrict the boundary of right index
// and the left index to prevent
// overflow of indices.
if (r >= l && l<arr.length-1) {

int mid = l + (r - l) / 2;

// If the element is present


// at the middle itself
if (arr[mid] == x)
return mid;

// If element is smaller than mid, then it


can only
// be present in left subarray
if (arr[mid] > x)
return binarySearch(arr, l, mid - 1, x);

// Else the element can only be present in


right
// subarray
return binarySearch(arr, mid + 1, r, x);
}

// We reach here when element is not present in


array
return -1;
}

// Driver method to test above


public static void main(String args[])
{
BinarySearch ob = new BinarySearch();
int arr[] = { 2, 3, 4, 10, 40 };
int n = arr.length;
int x = 10;
int result = ob.binarySearch(arr, 0, n - 1, x);
if (result == -1)
System.out.println("Element not present");
else
System.out.println("Element found at index "
+ result);
}
}
Result:

4. Exponential Recursion
An exponential recursive function is a function that, if you draw a representation of all
the function calls, will have an exponential number of calls about the size of the data set
(meaning exponential if there are n elements, there will be O (a) function calls where a is
a positive number). A great example of an exponentially recursive function is a function
for calculating all permutations of a data set. Let us write a function to take an array of n
integers and print each one.
clear print_array (int arr [], int n) {int i; for (i = 0; i <n; i) printf ("% d", arr [i]); printf
("\ n"); } void print_permutations (int arr [], int n, int i) {int j, swap; print_array (arr,
n); for (j = i + 1; j <n; j) {swap = arr [i]; arr [i] = arr [j]; arr [j] = exchange;
print_permutations (arr, n, i + 1); exchange = arr [i]; arr [i] = arr [j]; arr [j] =
exchange; }}
To run this function on an array of arrays of length n, we would do print_permutations
(arr, n, 0) where 0 tells to start over from the beginning of the array
Code:
import java.text.*;

class Exponential
{

// Recursive Function with static


// variables p and f
static double p = 1, f = 1;
static double e(int x, int n)
{
double r;

// Termination condition
if (n == 0)
return 1;

// Recursive call
r = e(x, n - 1);

// Update the power of x


p = p * x;

// Factorial
f = f * n;

return (r + p / f);
}

// Driver code
public static void main (String[] args)
{
int x = 4, n = 15;
DecimalFormat df = new DecimalFormat("0.######");
System.out.println(df.format(e(x, n)));
}
}
Result:

5. Nested Recursion
In nested recursion, one of the arguments for a recursive function is the recursive
function itself! This function tends to develop very quickly. A good example is the
classical math function, "Ackerman's function. It grows very fast (even for small values
of x and y, Ackermann (x, y) is very large) and cannot be computed by just iteration
definite (for () loops for example); it requires infinite iteration (recursion, for example).
Ackerman function int ackerman (int m, int n) {if (m == 0) return (n + 1); else if (n ==
0) return (ackerman (m-1,1)); else return (ackerman (m-1, ackerman (m, n-1))); }
Code:
public class Nested2 {
// Assumes n >= 0, m >= 0
public static int ack(int m, int n) {
if (m == 0) {
return n + 1;
}
else if (n == 0) {
return ack(m - 1, 1);
}
else {
return ack(m - 1, ack(m, n - 1));
}
}

public static void main(String[] args) {


System.out.println("A(0, 0) = " + ack(0, 0));
System.out.println("A(0, 1) = " + ack(0, 1));
System.out.println("A(1, 0) = " + ack(1, 0));
System.out.println("A(2, 1) = " + ack(2, 1));
System.out.println("A(1, 1) = " + ack(1, 1));
System.out.println("A(2, 2) = " + ack(2, 2));
}
}
Result:

tree

6. Mutual Recursion
Recursive functions do not need to call themselves. Some recursive functions work in
pairs or even in larger groups. For example, function A calls function B which calls
function C which in turn calls function A. A simple example of reciprocal recursion is a
series of functions for determining whether an integer is even or odd. How do we know if
a number is even? Well, we know 0 is even. And we also know that if a number n is
even, then n - 1 must be odd. How do we know if a number is odd? It is not even!
int is even (unsigned int n) {if (n == 0) return 1; else return (is odd (n-1)); } int is odd
(unsigned int n) {return (! is even (n)); }
The above situation is not the best example when we want to use recursion instead of
iteration or closed form solutions. A more efficient set of functions for determining
whether an integer is even or odd is as follows:
int is even (unsigned int n) {if (n% 2 == 0) return 1; else returns 0;} int is odd (unsigned
int n) {if (n% 2! = 0) return 1; else returns 0;}
Code:
import java .io.*;

class Mutual {

// Female function
static int hofstaderFemale(int n)
{
if (n < 0)
return 0;
else
return (n == 0) ? 1 : n -
hofstaderFemale(n - 1);
}

// Male function
static int hofstaderMale(int n)
{
if (n < 0)
return 0;
else
return (n == 0) ? 0 : n -
hofstaderMale(n - 1);
}

// Driver Code
static public void main (String[] args)
{
int i;
System.out.print("F: ");
for (i = 0; i < 20; i++)
System.out.print(hofstaderFemale(i)
+ " ");

System.out.println();

System.out.print("M: ");
for (i = 0; i < 20; i++)
System.out.print(hofstaderMale(i)
+ " ");
}
}
Result:

7. Head Recursion
If the recursive function calls itself and the recursive call is the first statement in the
function, then this is known as Head Recursion. No statement, no pre-call operation. The
function does not have to process or perform any operation at the time of calling and all
operations are performed at the time of return.
Code:
public class Head
{
public static void mistery(int x)
{
if(x>0)
mistery(x-1);

System.out.println(x);
}

public static void main(String[] args)


{
mistery(3);
}
}
Result:

8. Tree Recursion
Tree Recursion: To understand Tree Recursion, let's first understand Linear Recursion. If
a function is recursive calling itself for a time, then it is known as Linear Recursion.
Conversely, if a recursive function calls itself more than once then it is called Tree
Recursion.
Code:
class Node
{
int data;
Node left, right;

public Node(int item)


{
data = item;
left = right = null;
}
}

/* Class to find size of Binary Tree */


class BinaryTree
{
Node root;

/* Given a binary tree. Print its nodes in level order


using array for implementing queue */
int size()
{
return size(root);
}

/* computes number of nodes in tree */


int size(Node node)
{
if (node == null)
return 0;
else
return(size(node.left) + 1 + size(node.right));
}

public static void main(String args[])


{
/* creating a binary tree and entering the nodes */
BinaryTree tree = new BinaryTree();
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(3);
tree.root.left.left = new Node(4);
tree.root.left.right = new Node(5);

System.out.println("The size of binary tree is : "


+ tree.size());
}
}
Result:

9. Indirect Recursion
In this recursion, there may be more than one function and they call each other in a circle.
Code:
class Indirect
{
// We can avoid use of these using references
static final int N = 20;
static int n = 1;

// Prints n, increments n and calls fun1()


static void fun1()
{
if (n <= N)
{
System.out.printf("%d ", n);
n++;
fun2();
}
else
{
return;
}
}

// Prints n, increments n and calls fun2()


static void fun2()
{
if (n <= N)
{
System.out.printf("%d ", n);
n++;
fun1();
}
else
{
return;
}
}

// Driver Program
public static void main(String[] args)
{
fun1();
}
}
Result:

10. Single Recursion


A recursion that contains only one self-reference is called a single recursion, while a
recursion that contains multiple self-references is known as multiple recursions. Standard
examples of single recursion include browsing of lists, as in linear search, or computation
of factorial functions, while standard examples of double recursion include browsing of
trees, as in first deep search. Single recursion is often much more efficient than multiple
recursions, and can generally be replaced by iterative computing, runs in linear time, and
requires constant space. Some recursions, in contrast, may take exponential time and
space and is more inherently recursive, cannot be replaced by iterations without an
explicit stack
Code:
import java.util.Scanner;

public class SingleRecursion {

public static long factorial(int n) {


if (n<0) throw new IllegalArgumentException("Can't
calculate factorial of negative");
return (n<2) ? 1 : n*factorial(n-1);
}

public static void main(String[] args) {


Scanner stdIn = new Scanner(System.in);
System.out.print("Factorial of what number do you
want to calculate ");
int num = stdIn.nextInt();
System.out.printf("%d! = %d", num, factorial(num));

stdIn.close();
}

}
Result:

11. Multiple Recursions


Can sometimes be converted to a single recursion (and, if desired, then to iteration). For
example, when calculating the Fibonacci sequence naively it is multiple iterations since
each value requires two preceding values, this can be calculated by single recursion
passing two consecutive values as parameters. This is more naturally framed as
corecursion, constructing from an initial value, tracking at each step the two consecutive
values - see corecursion: example. A more sophisticated example is using a threaded
binary tree, which allows for looping hierarchy traversal instead of double recursion.
Code:
import java.util.Scanner;

public class MultipleRecursion {

public static long fibonacci(long n) {


if (n<0) throw new IllegalArgumentException("Can't
accept negative arguments");
return (n < 2) ? n : fibonacci(n-1) + fibonacci(n-
2);
}

public static void main(String[] args) {


Scanner stdIn = new Scanner(System.in);

System.out.print("How many numbers do you want to


print= ");
int iter = stdIn.nextInt();
for (int i=0;i<iter;i++) {
System.out.print(fibonacci(i) + " ");
}

stdIn.close();

}
Result:

12. Anonymous Recursion


Recursion is usually accomplished by explicitly calling a function by name. However,
recursion can also be performed via implicit function calls based on the current context,
which is very useful for anonymous functions and is known as anonymous recursion.
Code:
#include <stdio.h>
long fib(long x)
{
long fib_i(long n) { return n < 2 ? n : fib_i(n - 2)
+ fib_i(n - 1); };
if (x < 0) {
printf("Bad argument: fib(%ld)\n", x);
return -1;
}
return fib_i(x);
}

long fib_i(long n) /* just to show the fib_i() inside fib()


has no bearing outside it */
{
printf("This is not the fib you are looking for\n");
return -1;
}

int main()
{
long x;
for (x = -1; x < 4; x ++)
printf("fib %ld = %ld\n", x, fib(x));

printf("calling fib_i from outside fib:\n");


fib_i(3);

return 0;
}
Result:
13. Structural Recursion
The term "structural recursion" comes from the fact that this structure can be recursively
defined:
 A list does not mean anything, or the cells followed by a list.
 A binary tree means nothing or a node with two binary trees as children.
When performing structural recursion, you "undo" the operation from which these
structures are built on each other. For example, the NumberOfNodes function "undo"
construction takes a node and adds it to an existing list. The Find operator "undoes" the
binding operation of the node to the other two trees. Therefore, it's easy to see why this
function should be terminated - in the end, you "undo" all operations that were performed
to build the object in the first place, and the recursion stop
Code:
import java.util.Scanner;

public class Factorial {

public static void main(String[] args)


{
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the number whose factorial
is to be found: ");
int n = scanner.nextInt();
int result = factorial(n);
System.out.println("The factorial of " + n + " is
" + result);
}

public static int factorial(int num)


{
if (num==0)
{
return 1;
}
return num*factorial(num-1);
}
}
Result:

14. Generative Recursion


Recursive cases are generated based on the problem to be solved.
 The non-recursive case also does not follow the data definition.
 It is much more difficult to find a solution to such a problem.
 Often requires deeper analysis and domain-specific knowledge

Code:

import java.util.Scanner;

public class GCDExample1 {


public static void main(String[] args) {

int num1, num2;

//Reading the input numbers

Scanner scanner = new Scanner(System.in);

System.out.print("Enter first number:");

num1 = (int)scanner.nextInt();

System.out.print("Enter second number:");

num2 = (int)scanner.nextInt();

//closing the scanner to avoid memory leaks

scanner.close();

while (num1 != num2) {

if(num1 > num2)

num1 = num1 - num2;

else

num2 = num2 - num1;

//displaying the result


System.out.printf("GCD of given numbers is: %d",
num2);

System.out.println ("");

Result

15. Infinite Recursion


An infinite loop is a sequence of instructions in a computer program which loops
endlessly, either due to the loop having no terminating condition,[4] having one that can
never be met, or one that causes the loop to start over. In older operating systems with
cooperative multitasking,[5] infinite loops normally caused the entire system to become
unresponsive. With the now-prevalent preemptive multitasking model, infinite loops
usually cause the program to consume all available processor time but can usually be
terminated by the user. Busy wait loops are also sometimes called "infinite loops".
Infinite loops are one possible cause for a computer "freezing"; others include thrashing,
deadlock, and access violations.
Code:
#include <stdio.h>

int fun(int n)
{
if (n == 4)
return n;
else return 2*fun(n+1);
}
int main()
{
printf("%d ", fun(2));
return 0;
}
Result:

You might also like