Download presentation
Presentation is loading. Please wait.
1
Chapter 15 Recursive Algorithms
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
2
Chapter 15 Objectives After you have read and studied this chapter, you should be able to Write recursive algorithms for mathematical functions and nonnumerical operations. Decide when to use recursion and when not to. Describe the recursive quicksort algorithm and explain how its performance is better than that of selection and bubble sort algorithms. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
3
15.1 Basic Elements of Recursion
A recursive method is a method that contains a statement that makes a call to itself. Any recursive method will include the following three basic elements: A test to stop or continue the recursion. An end case that terminates the recursion. A recursive call that continues the recursion. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
4
15.1 Basic Elements of Recursion
These three elements are included in the following recursive factorial method: public int factorial(int N) { if (N == 1){ return 1; } else { return N* factorial(N-1); ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
5
15.2 Directory Listing Recursive algorithms may be used for nonnumerical applications. This example of a recursive algorithm will list the file names of all files in a given directory of a hard disk and its subdirectories. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
6
15.2 Directory Listing We create a new File object by passing the name of a file or a directory: File file = new File(“D:/Java/Projects”); To get an array of names of files and subdirectories, we use the list method. String[] fileList = file.list(); ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
7
15.2 Directory Listing Following is the complete directoryListing method (the argument of which is a File object that represents a directory): ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
8
15.2 Directory Listing public void directoryListing(File dir){
String[] fileList = dir.list(); //get the contents String dirPath = dir.getAbsolutePath(); for (int i=0; i<fileList.length; i++){ File file = new File(dirPath + “/” + fileList[i]); if(file.isFile()) { //it’s a file System.out.println(file.getName() ); }else{ directoryListing(file); //it’s a directory so recurse } ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
9
15.3 Anagram We can use a recursive method to derive all anagrams of a given word. When we find the end case (an anagram), we will print it out. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
10
Fig. 15.1 How to generate all the anagrams of a word by using recursion. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
11
15.3 Anagram We find the anagrams by rotating the positions of the letters. The trick is, when the method is called recursively, we pass a word with the first letter cut off. So the words being passed to successive calls are getting shorter and shorter. However, we must access all letters of the word in order to print it out. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
12
15.3 Anagram We solve this problem by passing two parameters: the prefix and the suffix of a word. In each successive call, the prefix increases by one letter and the suffix decreases by one letter. When the suffix becomes one letter only, the recursion stops. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
13
15.3 Anagram public void anagram(String prefix, String suffix) {
String newPrefix, newSuffix; int numOfChars = suffix.length(); if (numOfChars == 1){ //End case: print out one anagram System.out.println(prefix + suffix); }else{ ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
14
15.3 Anagram for (int i = 1; i <= numOfChars; i++){
newSuffix = suffix.substring(1, numOfChars); newPrefix = prefix + suffix.charAt(0); anagram(newPrefix, newSuffix); //recursive call //rotate left to create a //rearranged suffix suffix = newSuffix + suffix.charAt(0); } ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
15
15.4 Towers of Hanoi The goal of the Towers of Hanoi puzzle is to move N disks from peg 1 to peg 3: You must move one disk at a time. You must never place a larger disk on top of a smaller disk. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
16
Fig. 15.2 Towers of Hanoi with N=4 disks.
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
17
15.4 Towers of Hanoi This puzzle can be solved effectively using recursion. The top N-1 disks must be moved to peg 2, allowing you to then move the largest disk from peg 1 to peg 3. You can then move the N-1 disks from peg 2 to peg 3. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
18
Fig. 15.3 Recursive solution to the Towers of Hanoi puzzle.
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
19
15.4 Towers of Hanoi public void towersOfHanoi (int N,
int from, int to, int spare) { if (N == 1){ moveOne(from, to); }else{ towersOfHanoi(N-1, from, spare, to); moveOne (from, to); towersOfHanoi(N-1, spare, to, from); } private void moveOne(int from, int to){ System.out.println(from + “--” + to); ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
20
15.5 Quicksort The quicksort sorting algorithm uses recursion.
To sort an array from index low to high, we first select a pivot element p. Any element may be used for the pivot, but for this example we will user number[low]. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
21
Fig. 15.4 The core idea of the quicksort algorithm.
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
22
15.5 Quicksort Using p as the pivot, we scan through the array. We move all elements smaller than p to the lower half and all elements larger than p to the upper half. Then we sort the lower and upper halves recursively, using quicksort. The variable mid points to the position where the pivot is placed. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
23
15.5 Quicksort Here is the quicksort algorithm:
public void quickSort(int[] number, int low, int high){ if (low < high){ int mid = partition(number, low, high); quickSort(number, low, mid-1); quickSort(number, mid+1, high); } The partition method splits the array elements number[low] to number[high] into two halves. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
24
Fig. 15.5 Result of partitioning using 23 as a pivot.
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
25
15.5 Quicksort We first set the pivot to number[low].
We then look for a number smaller than the pivot from position high, high-1, and so on. The number is found at position J. We move this number to position low. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
26
15.5 Quicksort Now we look for a number larger than the pivot from low+1, low+2, etc. The number is found at position I. We move it to position J. We repeat the process, looking for a number smaller than the pivot from J-1, J-2, and so on. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
27
Fig. 15.6 Details of one partitioning.
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
28
Here is the partition method:
15.5 Quicksort Here is the partition method: private int partition(int[] number, int start, int end){ //set the pivot int pivot = number[start]; do{ //look for a number smaller than pivot //from the end while(start < end && number[end] >= pivot){ end--; } if(start < end){ //found a smaller number number[start] = number[end]; ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
29
15.5 Quicksort //now find a number larger than pivot //from the start
while(start < end && number[start] <= pivot){ start++; } if(start < end){ //found a larger number number[end] = number[start]; } while (start < end); //done, move the pivot back to the array number[start] = pivot; return start; ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
30
15.5 Quicksort In the worst case, quicksort executes roughly the same number of comparisons as the selection sort and bubble sort. On average, we can expect a partition process to split the array into two roughly equal subarrays. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
31
Fig. 15.7 A hierarchy of partitioning an array into smaller and smaller arrays in the quicksort. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
32
15.5 Quicksort When the size of all subarrays becomes 1, the array is sorted. The total number of comparisons for sorting the whole array is K * N N = 2K log2N = K KN = N log2N ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
33
15.6 When Not to Use Recursion
Recursion does not always provide an efficient or natural way to express the solution to a problem. public int fibonacci(int N){ if (N == 0 )|| N ==1){ return 1; //end case }else{ //recursive case return fibonacci(N-1) fibonacci(N-2); } ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
34
Fig. 15.8 Recursive calls to compute fibonacci(5).
©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
35
15.6 When Not to Use Recursion
This method is succinct and easy to understand, but it is very inefficient. A nonrecursive version is just as easy to understand. public int fibonacci(int N){ int fibN, fibN1, fibN2, cnt; if (N == 0 || N == 1){ return 1; }else{ fibN1 = fibN2 = 1; cnt = 2; ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
36
15.6 When Not to Use Recursion
while (cnt <= N){ fibN = fibN1 + fibN2; //get the next Fib. no. fibN1 = fibN2; fibN2 = fibN; cnt++; } return fibN; ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
37
15.6 When Not to Use Recursion
In general, use recursion if A recursive solution is natural and easy to understand. A recursive solution does not result in excessive duplicate computation. The equivalent iterative solution is too complex. ©TheMcGraw-Hill Companies, Inc. Permission required for reproduction or display.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.