Algorithm design techniques(recursion)

Ace your homework & exams now with Quizwiz!

2 terms added to get the Fibonacci number for a term

(N-2)+(n-1)

What the Fibonacci Sequence starts with

1 & 1

What is the output of tail(15)

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

real power(real x, int n )

1: if (x = 1) or (n = 0) then 2: return 1 3: else 4: if (n > 0) then 5: return x × power(x, n − 1) 6: end if 7: end if

Recursive calls Fibonacci Sequence makes

2 calls

Factorial, Fibonacci, Palindrome

3 common recursive algorithms

recursive definition

A definition in which something is defined in terms of a smaller version of itself.

mechanism of recursion

A function is recursive if its solution contains a call of the function itself as part of the solution for a given problem. Similarly, a program (or subprogram) is recursive if it contains a statement which calls itself as part of the solution.

fractal

A geometric shape in which certain patterns repeat, perhaps at a different scale and orientation.

indirectly recursive

A method that calls another method and eventually results in the original method call.

directly recursive

A method that calls itself.

recursive method

A method that calls itself.

Fractal

A pattern which produces a picture, which contains an infinite amount of copies of itself

tail recursive method

A recursive method in which the last statement executed is the recursive call.

Tail recursion

A recursive program is "tail-recursive" if only one recursive call appears in the program and that recursive call is the last operation performed at that recursive level. For example, Algorithm 3.4 is tail-recursive but Algorithm 3.6 is not. Tail recursive methods are desirable due to their relative space efficiency

Recursion

A subprogram can be referred as a method in Java. In most conventional computer languages, a method in Java, procedure or function in C can call itself. A subprogram that calls itself is said to be recursive or referred to as a recursive method, procedure or recursive function respectively

Ackermann function recursion

A(i,j)=|J+1 if i=1, j>= 1 |A(i-1,2) if i>=2, j=1 |A(i-1,A(i,j-1)) if i,j >=2

example of nested recursion

Ackermann function

is created every time a method is called, holds arguments, variables, return address

Activation Frame

Example of binary recursion pusedo code to solve the problem add all the nubers in an integer array a:

Algorithm BinarySum(A, i, n): Input: An array A and integers i and n Output: The sum of the n integers in A starting at indexi if n = 1 then return A[i] return BinarySum(A,i,n/2)+BinarySum(A,i+n/2,n/2)

Recursive squaring power function method pseudo code

Algorithm Power(x,n): Input: A number x and integer n=0 Output: The value x^n if n=0 then return 1 if n is odd then y=Power(x,(n-1)/2) return x*y*y else y=Power(x,n/2) return y*y

Example of reversing an array using tail recursion

Algorithm ReverseArray(A, i, j): Input: An array A and nonnegative integer indices i andj Output: The reversal of the elements in A starting at index i and ending at j if i < j then Swap A[i] and A[ j] ReverseArray(A,i+1,j-1) return

Example of Fibonacci Algorithm

Algorithm: LinearFibonacci(k) Input: A nonnegative integer k Output: A pair of Fibonacci numbers (F(k),F(k-1)) if k=1 then return (k,0) else (i,j)= LinearFibonacci(k-1) return (i+j,i)

Verifying the correctness of a recursive function is equivalent to verifying the following conditions: Step 2

All recursive calls of the function involve a case of the problem that is closer to one of the base case.

recursive algorithm

An algorithm that finds the solution to a given problem by reducing the problem to smaller versions of itself.

When coding the solution as a recursive function the following condition must be satisfied Step 2

Any recursive use of the function must move the problem closer to one of the base cases.

can only be performed on sorted array base case if array is empty or if target element is middle element algorithm if array is empty return -1; else if middle matches the target return subscript of middle element else if target is < middle element recursively search array elements before the middle element return result; else recursively search the elements to the right of middle element return result

Binary Search Algorithm

public static int binarySearch(Object items,Object target, int first, int last ) { //base case if (first>last) return -1; else int middle = first + last/2 int result = target.compareTo(items[middle]) if (result == 0) return middle; else if result< middle return binarySearch(items, first, middle-1) }

Binary Search Implementation

Recursion

Calls itself to help solve the problem in smaller parts

By drawing out the calls

Can trace a recursive solution

Merge step 1

Divide an n-element input sequence to be sorted into two subsequences of n/2 elements each.

The two basic step of quick sort step 1

Divide the array A[p..r] into two nonempty subarrays A[p..q]and A[(q + 1)..r] such that each element of A[p..q] is less than or equal to each element of A[(q + 1)..r]. The element q (called the pivot) is computed by the algorithm.

Recursive case(s)

Divide, invoke, combine

Iteration - complexity

Easier to approach

Recursion - ease of understanding

Easier to break Down

Question: In previous examples, which are the base cases and which are the inductive steps?

Example 3.3 Let us look at the well-known Fibonacci sequence 1, 1, 2, 3, 5, 8, 13, 21, 24, 34, .... Fibonacci sequence starts with two 1s. Each Fibonacci number thereafter is the sum of the two preceding numbers. This infinite sequence can be defined recursively by a1 = 1, a2 = 1 (Base case) an = an−1 + an−2, for n > 2 (Recursive step).

MC Eschers Drawing Hands

Example of recursion

Russian Nesting Dolls

Example of recursion

Sea shells, snail shells, elephant trunks, flowers, pineapples

Examples of Fibonacci in nature

Trees and snowflakes

Examples of recursion

Example of Factorial function f(n)=n!

F(n)= 1 if n=0 nf(n-1) if n>0

if n = 0 return 1 else n! = n(n-1)!

Factorial Algorithim

n! = n * (n-1)! (n > 0) ex. 4! = n * 3! ( 4 > 0) base case n = 0

Factorial Recursive

Common recursive programs

Factorials, Fibonacci, palindrome, drawing fractles

Fibonacci sequence

Find the nth term by adding the term before it and the term before that (n= (n-1)+(n-2))

Recursion - primary paradigm

Functional

Iteration - ease of understanding

Harder to track down Variables

Recursion - complexity

Harder to visualize

listMoves(int NumDisks, char StartPeg, LastPeg, SparePeg)

INPUT: The number of disks to move, the initial peg StartPeg, the destination peg LastPeg and the working peg SparePeg OUTPUT: Nothing (but display the moves) 1: if NumDisks = 1 then 2: writeln ("Move a disk from ", StartPeg, " to ", LastPeg) 3: else 4: ListMoves(NumDisks-1, StartPeg, SparePeg, LastPeg) 5: writeln ("Move a disk from ", StartPeg, " to ", LastPeg) 6: ListMoves(NumDisks-1, SparePeg, LastPeg, StartPeg) 7: end if

Iteration - primary paradigm

Imperative

what is recursion mathematically

In Mathematics, recursion is a process (or phenomenon) of finding solutions to a sequence of subproblems that are identical to the original problem but smaller in problem size.

recursive function composed of

In general, a function is said to be defined recursively if its definition consists of the following two parts: 1. Base case This must be a well defined termination 2. Inductive or recursive steps This consists of well defined inductive (or recursive) steps that must lead to a termination state

Example 3.6 (Towers of Hanoi problem) This is a game with a long history. There are 3 pegs (A, B, C) and a set of n disks of n different sizes. We mark them 1 · · · n with disk 1 the smallest, and n the largest (there are n = 64 disks in the legend). The n disks are to be moved from one peg to another, for example, from peg A to C. However, only one disk is allowed to be moved on each step and the disks must remain in the sorted order with the smallest on the top at any peg, so no disk is above a smaller one. Figure 3.1 shows that three disks on peg A need to be moved to peg C.

Let us summarise the problem again: Consider three pegs (A, B, C) and 3 disks (1, 2, 3) as in Figure 3.1, with disk 1 the smallest, and 3 the largest. Objective: to move the disks from peg A to C; Two rules: 1. one disk may be moved at a time 2. a larger disk can never be placed on a smaller disk. Suppose n is the number of disks. We take a recursive approach. 1. Base case: The solution for 1-disk problem (n = 1): Move the disk from peg A to peg C (Figure 3.2). 2. Inductive steps: (a) The solution for 2-disk problem (n = 2): i. Use the one-disk solution to move disk 1 to peg B, ii. then move disk 2 to peg C and iii. use the solution to the one-disk problem to move disk 1 to peg C

Enumeration

Looking for patterns in the code

Merge sort step 3

Merge the two sorted subsequences to produce the sorted sequence.

Base case in factorial solution

Num=0 or 1, report 1

Recursive squaring method runs

O(log n) time

The best-case efficiency of the quick sort

O(n log2 n)

The average run-time efficiency of the quick sort is

O(n log2 n),

The worst-case efficiency of the quick sort

O(n^2)

How can you recursively define the power function, P(x,n)=x^n

P(x,n)=|1 if n=0 |x *P(x, n-1) if n>0

Recursion and iteration have

Pros and cons

recursion function

Recursion is a powerful algorithmic tool for problem solving. As we shall see later, recursion is another way to realise repetition

Example of binary recursion peuso code

Recursive algorithm (first attempt): Algorithm BinaryFib(k): Input: Nonnegative integer k Output: The kth Fibonacci number Fk if k = 1 then return k else return BinaryFib(k - 1) + BinaryFib(k - 2)

The two basic step of quick sort step 2

Recursively call the Quick sort to sort A[p..q] and A[(q + 1)..r].

rightmost bit

Remainder of a number after division by 2.

For example, we defined the array reversal function as ReverseArray(A, i, j), an not

ReverseArray(A).

is a stack created by Java that holds activation frames it creates a new Activation frame every time a method is called.

Run Time Stack

Write recursive case so sprite moved to relocate angles and

Same size scaling factor of the parts of the fractal

Example 3.1 Given a non-negative integer n, compute n factorial

Solution 0!=1; 1!=1; for n>1, n!= n * (n-1)! For instance, when n = 5, 5! = 5 ∗ 4! = 5 ∗ 4 ∗ 3! = 5 ∗ 4 ∗ 3 ∗ 2! = 5 ∗ 4 ∗ 3 ∗ 2 ∗ 1! = 5 ∗ 4 ∗ 3 ∗ 2 ∗ 1

Example 3.2 Given n, an integer ≥ 0, and x, a real, compute the n consecutive powers of some number x.

Solution n = 0, xn = 1 n > 0, xn = x ∗ xn−1 For instance, when x = 3, n = 5, 30 = 1; 35 = 3 × 34, 34 = 3 × 33, 33 = 3 × 32, 32 = 3 × 31, 31 = 3 × 30 = 3 × 1.

Merge sort step 2

Sort the two subsequences recursively using merge sort

base case of quick sort

The base case is when there is one element to be sorted (which is returned as is because it is already sorted)

recursive case

The case in a recursive definition in which a smaller version of itself is called; general case.

general case

The case in a recursive definition in which a smaller version of itself is called; recursive case.

base case

The case in a recursive definition in which the solution is obtained directly.

Verifying the correctness of a recursive function is equivalent to verifying the following conditions: Step 1

The function contains (non-recursive) base cases.

Invoke

The function(recursively) on each part

Divide

The problem into 1 or more simpler/smaller parts

Base case

The problem is simple enough to be solved directly

recursion

The process of solving a problem by reducing it to successively smaller versions of itself.

Verifying the correctness of a recursive function is equivalent to verifying the following conditions: Step 3

The recursion properly implements the problem to be solved.

Combine

The solutions of the parts into a solution for the problem

Merge sort have time complexity

There are no best-case or worst-case

When coding the solution as a recursive function the following condition must be satisfied step 1

There must be at least one simple (base) case of the problem being solved that does not require recursion.

iterative control structures

Use a looping structure to repeat a set of statements.

Recursion - length of implementation

Uses fewer lines

Iteration - memory

Uses less memory

Iteration - length of implementation

Uses more lines

Recursion - memory

Uses more memory

Why recursion?

We first summarise the reasons and then look at an example. It may be the best way of thinking to solve some problems such as the Towers of Hanoi problem below. Algorithms can be very short as compared to an iterative version.It can help us understand certain problems. We may derive an iterative version later, based on the recursive one. In this way, a more efficient algorithm may be developed. the Quicksort algorithm.

Pick a base case that capture the part of the image which

Will be repeated throughout the image

C++ of void merge

___(int A[], int copyA[], int leftPos, int rightPos, int rightEnd) { int leftEnd = rightPos - 1; int j = leftPos; // index for copyA while (leftPos <= leftEnd && rightPos <= rightEnd) if ( A[leftPos] < A[rightPos] ) copyA[j++] = A[leftPos++]; else copyA[j++] = A[rightPos++]; // copy the rest while (leftPos <= leftEnd) copyA[j++] = A[leftPos++]; while (rightPos <= rightEnd) copyA[j++] = A[rightPos++]; }

c++ of Void mergeSort

____(int A[], int copyA[], int left, int right) { if (left < right) { int center = (left + right)/2; mergeSort(copyA, A, left, center); mergeSort(copyA, A, center+1, right); merge(A, copyA, left, center+1, right); } }

Indirect recursion

a function f () calls a function g() and the function g() calls the function f ().

When a function is called what information is stored 4

a returned value for a function (when not declared as void)

To define the method in ways that facilitate recursion then we must define

additional parameters that are passed to the method.

When a function is called what information is stored 1

alues for all formal parameters of the function

To describe quick sort

assume that we sort a subarray A[p..r]. The notation A[p..r] stands for an array with elements A[p], A[p + 1], . . . , A[r].

Why dose recursive squaring method runs at O(log n) time

because each time a recursive call is made it halve the value of n

Tail recursion

characterized by the use of only one recursive call at the end of a function.

classes that implement the comparable interface must define the compareTo() method

comparable interface

Merge sort Algorithm the copy A dose

copy of the array a

When a function is called what information is stored 3

ddress of the caller's instruction immediately following the call

In creating recursive methods, it is important

define the methods in ways that facilitate recursion.

Recursion:

defining the solution to a problem in terms of a simpler version of the same problem. It must eventually end in a version which does not contain any recursion at all and then immediately returns an answer through the preceding levels of recursive calls.

Recursive callings are represented internally by

different activation records s and are thus differentiated by the system

this information is stored dynamically using the

e run-time stack

if n = 0 return 1 else result is x* x^(n-1)

exponent Algorithm

Example of base case

factorial function the base case is n = 0.

factorail function

int factorial(int n) 1: if (n ≤ 1) then 2: return 1 3: else 4: return n × factorial(n − 1) 5: end

Recursive programs

int fibonacciItem(int n); (where n > 0) 1: if (n = 1) or (n = 2)) then 2: return 1 {where n > 0} 3: else 4: return fibonacciItem(n − 1) + fibonacciItem(n− 2) 5: end if

C++ quick sort main

int main(void) { int A[100]; ... // initialize the array A quicksort(A, 100); ... // use the sorted array A } void quicksort(int A[], int n) { quicksort(A, 0, n); } void quicksort(int A[], int low, int high) { if (low < high) { int middle = qsPartition(A, low, high); quicksort(A, low, middle); quicksort(A, middle+1, high); } }

Merge sort main

int main(void) { int A[100]; ... // initialize A mergeSort(A, 100); ... // use the sorted A }

Quick sort partition

int qsPartition(int A[], int low, int high) { int pivot = A[low]; int i = low-1, j = high+1; while (true) { do { j--; } while (pivot < A[j]); do { i++; } while (A[i] < pivot); if (i < j) { //swap A[i] and A[j] int temp = A[i]; A[i] = A[j]; A[j] = temp; } else return j; } }

most recursive implementations code

is shorter than it is in the non-recursive version

iteration has a condition that determines when to stop the loop recursions uses a base case, when it equals that case

iteration vs recursion

public static int factorial(int n) { int result = 1; for ( int k = 1; k<=n; k++) result = result * k return result; }

iterative factorial method

the recursively power function runs in

liner O(n) time( for we make n recursive calls)

private int size(Node head) { if (head == null) return 0; else return 1+size(head.next); }

linked List recursive size method

When a function is called what information is stored 2

local variables (which can be stored elsewhere, but then pointers to them must be stored)

C++ implementation of factorial

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

Iterative Factorial()

long factorialNonRecur(int n) { int result = 1; for (int k = n; k > 0; k--) result *= k; return result; }

The Merge Sort Algorithm left <= right denote

lower and upper indices of the subarray to be sorted

To handle recursion properly then a system

must create an activation record whenever a function is called

The average case of quick sort where

n is the number of elements in array to be sorted

Example of recursive step 2

n the factorial function the recursive call is factorial(n-1) which is one step closer than the original call factorial(n)

Is Merge sort practical

no Because the merge sort needs a duplicate copy of the array being sorted

In languages (such as C++ or Java) is there advantage ins using tail recursion over iteration

no in such languages tail recursion is not a recommendable feature.

When using the recursive squaring method do you call the method twice

no you have to use the variable twice

Binary recursion

occurs whenever there are two recursive calls for each non-base case.

Where is the activation record allocated

on the run-time stack

An activation record exists

or as long as a function owning it has not completed its execution, then it is removed from the stack by the system.

algorithm to improve the power function by repeated squaring for n=1 return 1n>0

p(x,n)| x *p(x,(n-1)/2)^2 if x >0, n odd | p(x,n/2)^2 if x >0, n even | 1 if x >0, n=0

The recursive version increases

program readability, improves self-documentation, and simplifies coding

find the largest integer that divides both numbers ex 20 and 15 GCD = 5 36 and 24 GCD = 12 given 2 positive integers n,m m> n if n is a divisor of m GCD of m and n = GCD(m,n) = (n, m%n)

recursive GCD

linked list is a recursive data structure Linked list either has a node or is empty

recursive Linked List

private void add(Node head, Object data) { if (head.next == null) head.next = new Node data else add(head.next, data) }

recursive add()

base case is empty array first element of array being search is target search rest of array minus the first element algorithm if array is empty return -1 else if first element of array match's target return subscript of element in array else search the array minus the first element implementation private static int search(Object[] items, Object target, int posFirst) { if (posFirst == items.length) return -1; else if (target.equals(items[posFirst])) return posFirst else return search(items, target, posFirst+1) }

recursive array search

Factorials Powers GCD

recursive examples

first check if n is <=2 and if so return 1, this is the base case, else return fib(n-1) + fib (n-2) fibonacci is a sequece that adds two numbers together, starts at n = 2 (2-1)+ (2-2) = 1 n = 3 (3-1) + (3-2) = 3 n = 4 (4-1) + (4-2) = 5

recursive fibo method

private boolean remove(Node head, Node pred, Object data) { if (head == null) return false; else if (head.data.equals(data) pred.next = head.next; //removes head return true; else return remove(head.next, pred, data)

recursive remove()

private void replace(Node head, Object old, Object new) { if (head != null) if(old.equals(head)) head.data = new; replace(head.next, old, new) }

recursive replace

private String toString(Node head) { if(head == null) return ""; else return head.data + toString(head.next) {

recursive toString()

Factorial (4) | V Factoria(0)

return 1 1*1=1 2*1=2 3*2=6 4*6=24

The merge sort requires

s O(n log2 n) comparisons

Nested recursion

s when a function not only calls itself but the function call is also used as one of the parameters

Recursion means calling a function of the

same name as the caller with the same formal arguments

The function mergeSort is

simple driver that declares a temporary array and calls the recursive function mergeSort

Quick sort

sorting algorithm based on recurrence.

Merge function in Merge sort

sorting itself

Sierpinski gasket

special type of fractal.

non-tail recursion example

static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; void printHexadecimal(int n) { if (n >= 16) printHexadecimal(n/16); cout << hexDigits[n % 16]; }

implementation of recursion

static int fibonacciItem(int n) { int f=0; if (n=1) || (n=2) { f=1;} else{ f=fibonacciItem(n-1)+fibonacciItem(n-2);} return f;} static int factorial(int n) { int f=0; if (n<2) { f=1;} else{ f=n*factorial(n-1);} return f;} static double power(double x, int n) { double p=0.0; if ((x==1) || (n==0)) { p=1; } else if (n>0) { p=x*power(x, n-1); } return p; }

The worst case for the algorithm is when

the array is already sorted and depend on the choice of the pivotal element(pivot)

In a tail recursion

the recursive call is the last statement

The Droste effect

the result of a picture recursively appearing within itself, in a place where a similar picture would realistically be expected to appear.

Activation record (stack frame)

the set set of information that is called

In C++, the prefix 0x is used

to represent hexadecimal numbers

Merge sort

uses recursion to sort an array of numbers

Merge sort function

void mergeSort(int A[], int n) { int *copyA = new int[n]; for (int i = 0; i < n; i++) copyA[i] = A[i]; mergeSort(copyA, A, 0, n-1); delete [] copyA; }

Example of tail recursion

void tail(int n) { if (n > 0) { cout << n << " "; tail(n - 1); } else cout << endl; }

example of tail function using iterative approach

void tailNonRecur(int n) { for (int k = n; k > 0; k--) cout << k << " "; cout << endl; }

Merge sort base case

when the subsequence contains one or zero elements (which are already sorted).

is a tail recursion like a loop

yes

In language(such as Prolog,Lisp) is there advantage in using tail recursion over iteration

yes such language have explicit loop constructs so tail recursion is important


Related study sets

Chapter 1- An Overview of Organizational Behavior

View Set

Abnormal Psychology Chapters 10-15 Multiple Choice

View Set

U.S. Presidents (in order) last names only

View Set

final exam- the ear and hearing and equilibrium

View Set

Chapter 7: Incremental Analysis for Short Term Decision Making

View Set