Towers of Hanoi

In the preceding sections of this chapter, we studied methods that can be easily implemented both recursively and iteratively. In this section, we present a problem whose recursive solution demonstrates the elegance of recursion, and whose iterative solution may not be as apparent.

The Towers of Hanoi is one of the most famous classic problems every budding computer scientist must grapple with. Legend has it that in a temple in the Far East, priests are attempting to move a stack of golden disks from one diamond peg to another (Fig. 15.14). The initial stack has 64 disks threaded onto one peg and arranged from bottom to top by decreasing size. The priests are attempting to move the stack from one peg to another under the constraints that exactly one disk is moved at a time and at no time may a larger disk be placed above a smaller disk. Three pegs are provided, one being used for temporarily holding disks. Supposedly, the world will end when the priests complete their task, so there is little incentive for us to facilitate their efforts.

Figure 15.14. Towers of Hanoi for the case with four disks.

Let us assume that the priests are attempting to move the disks from peg 1 to peg 3. We wish to develop an algorithm that prints the precise sequence of peg-to-peg disk transfers.

If we were to approach this problem with conventional methods, we would rapidly find ourselves hopelessly knotted up in managing the disks. Instead, attacking this problem with recursion in mind allows the steps to be simple. Moving n disks can be viewed in terms of moving only n - 1 disks (hence the recursion) as follows:

  1. Move n - 1 disks from peg 1 to peg 2, using peg 3 as a temporary holding area.
  2. Move the last disk (the largest) from peg 1 to peg 3.
  3. Move the n - 1 disks from peg 2 to peg 3, using peg 1 as a temporary holding area.

The process ends when the last task involves moving n = 1 disk (i.e., the base case). This task is accomplished by simply moving the disk, without the need for a temporary holding area.

Figure 15.15 displays the precise instructions it will take to move the disks from the starting peg to the destination peg. In the constructor (lines 912), the number of disks to be moved (numDisks) is initialized. Method solveTowers (lines 1534) solves the Towers of Hanoi puzzle given the total number of disks (in this case 3 ), the starting peg, the ending peg, and the temporary holding peg as parameters. The base case (lines 1923) occurs when only one disk needs to be moved from the starting peg to the ending peg. In the recursion step (lines 2733), line 27 moves disks - 1 disks from the first peg (sourcePeg) to the temporary holding peg (tempPeg). When all but one of the disks have been moved to the temporary peg, line 30 records the step to move one disk, the largest one, from the start peg to the destination peg. Line 33 finishes the rest of the moves by calling the method solveTowers to recursively move disks - 1 disks from the temporary peg (tempPeg) back to the destination peg (destinationPeg), this time using the first peg (sourcePeg) as the temporary peg.

Figure 15.15. Towers of Hanoi solution with a recursive method.

1 // Fig. 15.15: TowersOfHanoi.java 2 // Program solves the towers of Hanoi problem, and 3 // demonstrates recursion. 4 5 public class TowersOfHanoi 6 { 7 int numDisks; // number of disks to move 8 9 public TowersOfHanoi( int disks ) 10 { 11 numDisks = disks; 12 } // end TowersOfHanoi constructor 13 14 // recusively move disks through towers 15 public void solveTowers( int disks, int sourcePeg, int destinationPeg, 16 int tempPeg ) 17 { 18 // base case -- only one disk to move 19 if ( disks == 1 ) 20 { 21 System.out.printf( " %d --> %d", sourcePeg, destinationPeg ); 22 return; 23 } // end if 24 25 // recursion step -- move disk to tempPeg, then to destinationPeg 26 // move ( disks - 1 ) disks from sourcePeg to tempPeg recursively 27 solveTowers( disks - 1, sourcePeg, tempPeg, destinationPeg ); 28 29 // move last disk from sourcePeg to destinationPeg 30 System.out.printf( " %d --> %d", sourcePeg, destinationPeg ); 31 32 // move ( disks - 1 ) disks from tempPeg to destinationPeg 33 solveTowers( disks - 1, tempPeg, destinationPeg, sourcePeg ); 34 } // end method solveTowers 35 } // end class TowersOfHanoi

Figure 15.16 tests our Towers of Hanoi solution. In the main method (lines 616), line 12 creates a TowersOfHanoi object, passing as a parameter the total number of disks to be moved from one peg to another. Line 15 calls the recursive solveTowers method which outputs the steps to the command prompt.

Figure 15.16. Testing the Towers of Hanoi solution.

1 // Fig. 15.16: TowersOfHanoiTest.java 2 // Test the solution to the Towers of Hanoi problem. 3 4 public class TowersOfHanoiTest 5 { 6 public static void main( String args[] ) 7 { 8 int startPeg = 1; // value 1 used to indicate startPeg in output 9 int endPeg = 3; // value 3 used to indicate endPeg in output 10 int tempPeg = 2; // value 2 used to indicate tempPeg in output 11 int totalDisks = 3; // number of disks 12 TowersOfHanoi towersOfHanoi = new TowersOfHanoi( totalDisks ); 13 14 // initial nonrecursive call: move all disks. 15 towersOfHanoi.solveTowers( totalDisks, startPeg, endPeg, tempPeg ); 16 } // end main 17 } // end class TowersOfHanoiTest  

1 --> 3 1 --> 2 3 --> 2 1 --> 3 2 --> 1 2 --> 3 1 --> 3  

Категории