Towers of Hanoi
In the great temple of Brahma in Benares group of spiritually advanced monks have to move 64 golden disks from one diamond needle to another. And, there is only one other location in the temple (besides the original and destination locations) sacred enough that a pile of disks can be placed there. The 64 disks have different sizes, and the monks must obey two rules:The legend is that, before the monks make the final move to complete the new pile in the new location, the next Maha Pralaya will begin and the temple will turn to dust and the world will end. Is there any truth to this legend?
- only one disk can be moved at a time
- a bigger disk can never be placed on a top of a smaller disk.
The Tower of Hanoi puzzle was invented by the French mathematician Edouard Lucas in 1883. The puzzle is well known to students of Computer Science since it appears in virtually any introductory text on data structures or algorithms.
Recursive implementation
public int hanoi(int n) { if (n == 1) return 1; else return 2*hanoi(n-1) + 1; }The idea of calling one function from another immediately suggests the possibility of a function calling itself.
Recurrent equation for the number of moves
T(n) = 2*T(n-1) + 1
Recursive Drawing
For-loops are sooo old fashioned
Example 1 A sum of natural numbers
1 + 2 + 3 + ... + n
iterative implementation recursive implementation
public int sum(int n) public int sumR(int n) { { int res = 0; if(n == 1) for(int i = 1; i ≤ n; i++) return 1; res = res + i; else return n + sumR(n-1); return res; } }
Let us trace the sequence of recursive calls of
sumR(5)
sumR(5) sumR(4) sumR(3) sumR(2) sumR(1) return 1 return 2 + 1 return 3 + 2 + 1 return 4 + 3 + 2 + 1 return 5 + 4 + 3 + 2 + 1
Binary Search
Locate the element x in a sorted array by first comparing x with the middle element and then (if they are not equal) dividing the array into two subarrays and repeat the whole procedure in one of them. If x is less than the middle element you search in the left subarray, otherwise - in the right subarray.
Recurrent equation
T(n) = T(n/2) + 1
public int searchR(int[] a, int key) { return helper(a, key, 0, a.length-1); } private int helper(int[] a, int key, int left, int right) { if (left > right) return -1; int mid=(left+right)/2; if (key == a[mid]) return mid; else if (key > a[mid]) return helper(a, key, mid + 1, right); else return helper(a, key, left, mid - 1); }
Merge Sort
- Divide the array into two subarrays
- Sort each subarray
- Merge them into one (in a smart way!)
Recurrent equation
T(n) = 2*T(n/2) + n
public void mergeSort(int [ ] a) { int[] tmp = new int[a.length]; mergeSort(a, tmp, 0, a.length - 1); } private void mergeSort(int [ ] a, int [ ] tmp, int left, int right) { if( left < right ) { int center = (left + right) / 2; mergeSort(a, tmp, left, center); mergeSort(a, tmp, center + 1, right); merge(a, tmp, left, center + 1, right); } }
Recursive Data Structures
Stack - A stack is either empty or consists of a top and the rest which is a stack.
Linked List - A linked list is either empty or consists of a node followed by a linked list.
Tree - A tree is either empty or consists of one node called root and zero or more subtrees.
Mathematical Induction
Recursive programming is directly related to mathematical induction
The base case is to prove the statement true for some specific value or values of N.
The induction step -- assume that a statement is true for all positive integers less than N,then prove it true for N.
A few exercises
1. Consider the following mystery method:
public static void mystery(int level) { if (level == 0) System.out.print("*"); else { System.out.print("["); mystery(level - 1); System.out.print(","); mystery(level - 1); System.out.print("]"); }
Show the output that would be produced by the following calls
- mystery(1);
- mystery(2);
2. Examine the following code segment
public class Demo { public static void main(String[] ags) { System.out.println( fun(5) ); } public static int fun(int n) { if (n == 0) return 1; else return n + fun(n/2); } }and predict the output
- A) 5
- B) 7
- C) 8
- D) 9
3. Consider the following method. What does it do?
public int foobar(int x, int y) { if (y == 0) return 1; if (y%2 == 1) return x*foobar(x*x, y/2); else return foobar(x*x, y/2); }
Exercise. Write a recursive method that prints the following pattern?
##### #### ### ## #
# ## ### #### #####
Fibonacci Numbers
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
Each number is the sum of the two preceding numbers.
Fibonacci was born 1170 in Pisa, Italy and died in 1250. His real name is Leonardo Pisano. In 1202 he wrote a book: Liber Abbaci, meaning "Book of Calculating". It helped bring arithmetic in Europe up to Arab standards
public int fibonacci(int n) { if (n ≤ 0) return 0; else if (n == 1) return 1 else return fibonacci(n-1) + fibonacci(n-2); }
The Mandelbrot Set
The Mandelbrot set is the set of all complex numbers c for which sequence defined by the iteration
f(n+1) = f(n)2 + c, f(0) = cremains bounded for n = 0, 1, 2, 3, ....
f(3) = f(2)2 + c = = ( f(1)2 + c )2 + c = ( ( f(0)2 + c )2 + c )2 + c = ( ( c2 + c )2 + c )2 + c
A few examples.
Let c = 1. This sequence is NOT bounded f(0) = 1 2 f(1) = f(0) + 1 = 2 2 f(2) = f(1) + 1 = 5 2 f(3) = f(2) + 1 = 26
Let c = 0.1 This sequence has a fixed point f(0) = 0.1 2 f(1) = f(0) + 0.1 = 0.11 2 f(2) = f(1) + 0.1 = 0.1121 2 f(3) = f(2) + 0.1 = 0.112566 ... f(8) = 0.112702
Our goal is to draw all complex c = x + I * y for which function f(n ) stays bounded or converges to a fixed point.
Linked Lists Recursively
Implement
public String toString() public void insertAfter(Object key, Object toInsert) public void insertBefore(Object key, Object toInsert) public void delete(Object key) public LinkedList clone() public void insertInOrder(Comparable key)
Gray Code
A Gray code is an encoding of numbers so that every transition from one value to the next value involves only one bit change. The following are 2, 3 and 4 bit Gray codes
Decimal Binary Gray 0 00 00 1 01 01 2 10 11 3 11 10
Decimal Binary Gray 0 000 000 1 001 001 2 010 011 3 011 010 4 100 110 5 101 111 6 110 101 7 111 100
Decimal Binary Gray 0 0000 0000 1 0001 0001 2 0010 0011 3 0011 0010 4 0100 0110 5 0101 0111 6 0110 0101 7 0111 0100 8 1000 1100
The n bit code is generated by
- prepending 0 to each (n-1) bit code
- prepending 1 to each (n-1) bit code in reverse order
Write a recursive program that prints out the n-bit binary Gray code.