Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Decision-Making and Repetition 2.2 Recursion Introduction A recursive method is a method that call itself. You may already be familiar with the factorial function (N!) in mathematics. For any positive integer N, N! is defined to be the product of all integers between 1 and N inclusive. N! = 1 * 2 * 3 * 4 * 5 * … N-1 * N Another way of expressing N! is by using recursion. i.e. by having the function call itself. N! = N * (N – 1)! where N > 1, and 1! = 1 Note that the recursion terminates when N = 1. This is known as the base case. This can be visualised as follows: 5! = 5 * 4! = 5 * 4 * 3! = 5 * 4 * 3 * 2! = 5 * 4 * 3 * 2 * 1! = 5 * 4 * 3 * 2 * 1 From this example we can see that without a base case, the recursions could go on indefinitely. The code in a recursive method must be have both the recursive part and the base case. Although recursion can sometimes provide elegant solutions based on recursive thinking as shown above, this does not mean that recursive solutions are the best. Recursion makes huge demands on memory, and should only be used when it significantly simplifies the code. 1 Decision-Making and Repetition Recursive Method Example A recursive method is a method that calls itself. For example, below is a recursive method which prints out asterisks on line or the word “Done!” public static void drawStars(int rows) { if(rows == 0) System.out.println("There are no stars in this row!"); else { for(int i = 1; i <= rows; i++) System.out.print("*"); System.out.println(); drawStars(rows - 1); //drawStars calls itself } } Note that this method takes in an integer parameter. So instead of using String [] args inside the parenthesis following the method name, we have int rows – highlighted above. The base case is rows == 0, and the method calls itself using the parameter rows – 1. As we will see in the demos, when the drawStars method is run we will need to enter the specific value we want it to use during the execution. For example, when the integer 5 is entered, we get the following result: ***** **** *** ** * There are no stars in this row! Most of the time, return methods require a return statement as part of their definition. So it is worth spending some time discussing these. 2 Decision-Making and Repetition Return Statements Until now, our programs have included a main method of the form: public static void main (String[] args) Control is automatically passed on to a main method within a program when a Java program is executed. For this reason, a Java application (or program) can only have one main method. A main method is void, which means that does not return any value. This is why so far we have had to use the System.out.println to output values computed within a main method. A non-void method must return a specific data type. For example, the template class provided when a new class is created in BlueJ includes the non-void method shown below. public int sampleMethod(int y) { // put your code here return x + y; } sampleMethod returns a value of type int, and therefore must contain a return statement as part of its definition. Methods with a non-void return type are usually written inside a class representing an object, and later called by the main method or in another class—sometimes referred to as the driver class. Here is an example: 3 Decision-Making and Repetition Assume the following method deposit is part of a class which represents the bank accounts of customers at a certain bank. public double deposit (double amount) { if (amount < 0) // deposit value is negative { System.out.println (); System.out.println ("Error: Deposit amount is invalid."); } else balance += amount; return balance; } This method could be called within another class – call it CustomerAccounts – using the following statement, which is used to deposit £500 into a Mr Smith’s account double smithBalance = smithAcc.deposit (800.00); //note call to deposit method Following which the new balance could be printed out with the following statement written inside CustomerAccounts. System.out.println ("Smith balance after deposit: " + smithBalance); Writing Recursive Methods The drawStars method above is an example of tail recursion, since the recursive call is the last statement in the method. When drawStars is called within the method, the value of the parameter must be smaller than that used in the original call. In other words, the value most continue to progress towards the base case. Without this type of set up, the method will continue to execute infinitely; this is known as infinite recursion. Two well-known examples of recursion are the Fibonacci sequence and the Tower of Hanoi; both of these are covered in the Mathematics sections this week. This section concludes with an analysis of a method to find the nth Fibonacci number. 4 Decision-Making and Repetition Given the Fibonacci sequence 1, 1, 2, 3, 5, 8, 13, … let us calculate the nth Fibonacci number. Recall that except for the first two numbers in the sequence, every Fibonacci number is the sum of the preceding two numbers. This is written mathematically as, 𝐹𝑖𝑏(𝑛) = { 1 𝑖𝑓 𝑛 = 1 𝑜𝑟 2 𝐹𝑖𝑏(𝑛 − 1) + 𝐹𝑖𝑏(𝑛 − 2) 𝑖𝑓 𝑛 ≥ 3 Once it has been written in this recursive format, it becomes straightforward to write Java code to calculate the nth Fibonacci number. This is shown below. public static int fibo(int n) { if (n == 1 || n == 2) return 1; else return fibo(n - 1) + fibo (n - 2); } fibo also has tail recursion since the recursive call is the last statement in the method. But notice that there are actually two recursive calls—fibo(n - 1) and fibo (n - 2). Actually, calling fibo(n) for n = 3, calls fibo(2) and fibo(1); that’s two recursive calls. Now fibo(4) = fibo(3) + fibo(2). From above, fibo(3)makes two further recursive calls, plus one more. So there are four recursive calls. 5 Decision-Making and Repetition We can see how complex this computation gets very quickly from the tree structure for fibo(5)shown below. fibo(5) fibo(4) fibo(3) fibo(2) fibo(3) fibo(2) fibo(2) fibo(1) This shows that executing fibo(5) requires a further 8 calls to fibo! 6 fibo(1)