数据结构与算法 - 河内塔


河内塔是一个数学难题,由三座塔(钉子)和多个环组成,如图所示 -

河内塔

这些环大小不同,并按升序堆叠,即较小的环位于较大的环之上。该谜题还有其他变体,其中圆盘数量增加,但塔数保持不变。

规则

任务是将所有圆盘移动到另一个塔而不违反排列顺序。河内塔需要遵循的一些规则是 -

  • 在任何给定时间,只能在塔之间移动一个圆盘。
  • 只能移除“顶部”磁盘。
  • 没有大磁盘可以位于小磁盘之上。

以下是用三个圆盘解决河内塔谜题的动画演示。

河内塔

具有 n 个圆盘的汉诺塔谜题可以通过最少2 n −1步来解决。该演示显示,一个包含 3 个圆盘的拼图需要2 3 - 1 = 7 个步骤。

算法

要为河内塔编写算法,首先我们需要学习如何用更少的磁盘来解决这个问题,比如 → 1 或 2。我们用 name、 sourcedestinationaux标记三个塔(只是为了帮助移动磁盘)。如果我们只有一个磁盘,那么可以轻松地将其从源桩移动到目标桩。

如果我们有 2 个磁盘 -

  • 首先,我们将较小的(顶部)磁盘移动到辅助挂钩。
  • 然后,我们将较大(底部)的磁盘移动到目标挂钩。
  • 最后,我们将较小的磁盘从 aux 移动到目标挂钩。
有两个圆盘的河内塔

现在,我们可以为具有两个以上磁盘的汉诺塔设计算法。我们将磁盘堆栈分为两部分。最大的圆盘(第 n圆盘)位于一部分中,所有其他 (n-1) 个圆盘位于第二部分中。

我们的最终目标是将磁盘n从源移动到目标,然后将所有其他 (n1) 磁盘放入其中。我们可以想象以递归方式对所有给定的磁盘集应用相同的方法。

要遵循的步骤是 -

Step 1 − Move n-1 disks from source to aux
Step 2 − Move nth disk from source to dest
Step 3 − Move n-1 disks from aux to dest

河内塔的递归算法可以按如下方式驱动 -

START
Procedure Hanoi(disk, source, dest, aux)

   IF disk == 1, THEN
      move disk from source to dest             
   ELSE
      Hanoi(disk - 1, source, aux, dest)     // Step 1
      move disk from source to dest          // Step 2
      Hanoi(disk - 1, aux, dest, source)     // Step 3
   END IF
   
END Procedure
STOP

例子

#include <stdio.h> #include <stdbool.h> #define MAX 10 int list[MAX] = {1,8,4,6,0,3,5,2,7,9}; void display(){ int i; printf("["); // navigate through all items for(i = 0; i < MAX; i++) { printf("%d ",list[i]); } printf("]\n"); } void bubbleSort() { int temp; int i,j; bool swapped = false; // loop through all numbers for(i = 0; i < MAX-1; i++) { swapped = false; // loop through numbers falling ahead for(j = 0; j < MAX-1-i; j++) { printf("Items compared: [ %d, %d ] ", list[j],list[j+1]); // check if next number is lesser than current no // swap the numbers. // (Bubble up the highest number) if(list[j] > list[j+1]) { temp = list[j]; list[j] = list[j+1]; list[j+1] = temp; swapped = true; printf(" => swapped [%d, %d]\n",list[j],list[j+1]); } else { printf(" => not swapped\n"); } } // if no number was swapped that means // array is sorted now, break the loop. if(!swapped) { break; } printf("Iteration %d#: ",(i+1)); display(); } } int main() { printf("Input Array: "); display(); printf("\n"); bubbleSort(); printf("\nOutput Array: "); display(); }

输出

Input Array: [1 8 4 6 0 3 5 2 7 9 ]

Items compared: [ 1, 8 ]  => not swapped
Items compared: [ 8, 4 ]  => swapped [4, 8]
Items compared: [ 8, 6 ]  => swapped [6, 8]
Items compared: [ 8, 0 ]  => swapped [0, 8]
Items compared: [ 8, 3 ]  => swapped [3, 8]
Items compared: [ 8, 5 ]  => swapped [5, 8]
Items compared: [ 8, 2 ]  => swapped [2, 8]
Items compared: [ 8, 7 ]  => swapped [7, 8]
Items compared: [ 8, 9 ]  => not swapped
Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ]
Items compared: [ 1, 4 ]  => not swapped
Items compared: [ 4, 6 ]  => not swapped
Items compared: [ 6, 0 ]  => swapped [0, 6]
Items compared: [ 6, 3 ]  => swapped [3, 6]
Items compared: [ 6, 5 ]  => swapped [5, 6]
Items compared: [ 6, 2 ]  => swapped [2, 6]
Items compared: [ 6, 7 ]  => not swapped
Items compared: [ 7, 8 ]  => not swapped
Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ]
Items compared: [ 1, 4 ]  => not swapped
Items compared: [ 4, 0 ]  => swapped [0, 4]
Items compared: [ 4, 3 ]  => swapped [3, 4]
Items compared: [ 4, 5 ]  => not swapped
Items compared: [ 5, 2 ]  => swapped [2, 5]
Items compared: [ 5, 6 ]  => not swapped
Items compared: [ 6, 7 ]  => not swapped
Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [ 1, 0 ]  => swapped [0, 1]
Items compared: [ 1, 3 ]  => not swapped
Items compared: [ 3, 4 ]  => not swapped
Items compared: [ 4, 2 ]  => swapped [2, 4]
Items compared: [ 4, 5 ]  => not swapped
Items compared: [ 5, 6 ]  => not swapped
Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ]
Items compared: [ 0, 1 ]  => not swapped
Items compared: [ 1, 3 ]  => not swapped
Items compared: [ 3, 2 ]  => swapped [2, 3]
Items compared: [ 3, 4 ]  => not swapped
Items compared: [ 4, 5 ]  => not swapped
Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ]
Items compared: [ 0, 1 ]  => not swapped
Items compared: [ 1, 2 ]  => not swapped
Items compared: [ 2, 3 ]  => not swapped
Items compared: [ 3, 4 ]  => not swapped

Output Array: [0 1 2 3 4 5 6 7 8 9 ]
// C++ Code for Tower of Hanoi #include <iostream> #include <array> #include <algorithm> const int MAX = 10; std::array<int, MAX> list = {1, 8, 4, 6, 0, 3, 5, 2, 7, 9}; void display() { std::cout << "["; // navigate through all items for (int i = 0; i < MAX; i++) { std::cout << list[i] << " "; } std::cout << "]\n"; } void bubbleSort() { int temp; bool swapped = false; // loop through all numbers for (int i = 0; i < MAX - 1; i++) { swapped = false; // loop through numbers falling ahead for (int j = 0; j < MAX - 1 - i; j++) { std::cout << "Items compared: [" << list[j] << ", " << list[j+1] << "] "; // check if next number is lesser than current no // swap the numbers. // (Bubble up the highest number) if (list[j] > list[j+1]) { std::swap(list[j], list[j+1]); swapped = true; std::cout << "=> swapped [" << list[j] << ", " << list[j+1] << "]\n"; } else { std::cout << "=> not swapped\n"; } } // if no number was swapped that means // array is sorted now, break the loop. if (!swapped) { break; } std::cout << "Iteration " << (i+1) << "#: "; display(); } } int main() { std::cout << "Input Array: "; display(); std::cout << "\n"; bubbleSort(); std::cout << "\nOutput Array: "; display(); return 0; }

输出

Input Array: [1 8 4 6 0 3 5 2 7 9 ]

Items compared: [1, 8] => not swapped
Items compared: [8, 4] => swapped [4, 8]
Items compared: [8, 6] => swapped [6, 8]
Items compared: [8, 0] => swapped [0, 8]
Items compared: [8, 3] => swapped [3, 8]
Items compared: [8, 5] => swapped [5, 8]
Items compared: [8, 2] => swapped [2, 8]
Items compared: [8, 7] => swapped [7, 8]
Items compared: [8, 9] => not swapped
Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ]
Items compared: [1, 4] => not swapped
Items compared: [4, 6] => not swapped
Items compared: [6, 0] => swapped [0, 6]
Items compared: [6, 3] => swapped [3, 6]
Items compared: [6, 5] => swapped [5, 6]
Items compared: [6, 2] => swapped [2, 6]
Items compared: [6, 7] => not swapped
Items compared: [7, 8] => not swapped
Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ]
Items compared: [1, 4] => not swapped
Items compared: [4, 0] => swapped [0, 4]
Items compared: [4, 3] => swapped [3, 4]
Items compared: [4, 5] => not swapped
Items compared: [5, 2] => swapped [2, 5]
Items compared: [5, 6] => not swapped
Items compared: [6, 7] => not swapped
Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [1, 0] => swapped [0, 1]
Items compared: [1, 3] => not swapped
Items compared: [3, 4] => not swapped
Items compared: [4, 2] => swapped [2, 4]
Items compared: [4, 5] => not swapped
Items compared: [5, 6] => not swapped
Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ]
Items compared: [0, 1] => not swapped
Items compared: [1, 3] => not swapped
Items compared: [3, 2] => swapped [2, 3]
Items compared: [3, 4] => not swapped
Items compared: [4, 5] => not swapped
Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ]
Items compared: [0, 1] => not swapped
Items compared: [1, 2] => not swapped
Items compared: [2, 3] => not swapped
Items compared: [3, 4] => not swapped

Output Array: [0 1 2 3 4 5 6 7 8 9 ]
//Java Code for Tower of Hanoi import java.util.Arrays; public class BubbleSort { public static final int MAX = 10; public static int[] list = {1, 8, 4, 6, 0, 3, 5, 2, 7, 9}; public static void display() { System.out.print("["); // navigate through all items for (int i = 0; i < MAX; i++) { System.out.print(list[i] + " "); } System.out.println("]"); } public static void bubbleSort() { boolean swapped; // loop through all numbers for (int i = 0; i < MAX - 1; i++) { swapped = false; // loop through numbers falling ahead for (int j = 0; j < MAX - 1 - i; j++) { System.out.print("Items compared: [" + list[j] + ", " + list[j + 1] + "] "); // check if next number is lesser than current no // swap the numbers. // (Bubble up the highest number) if (list[j] > list[j + 1]) { int temp = list[j]; list[j] = list[j + 1]; list[j + 1] = temp; swapped = true; System.out.println("=> swapped [" + list[j] + ", " + list[j + 1] + "]"); } else { System.out.println("=> not swapped"); } } // if no number was swapped that means // array is sorted now, break the loop. if (!swapped) { break; } System.out.print("Iteration " + (i + 1) + "#: "); display(); } } public static void main(String[] args) { System.out.print("Input Array: "); display(); System.out.println(); bubbleSort(); System.out.print("\nOutput Array: "); display(); } }

输出

Input Array: [1 8 4 6 0 3 5 2 7 9 ]
Items compared: [1, 8] => not swapped
Items compared: [8, 4] => swapped [4, 8]
Items compared: [8, 6] => swapped [6, 8]
Items compared: [8, 0] => swapped [0, 8]
Items compared: [8, 3] => swapped [3, 8]
Items compared: [8, 5] => swapped [5, 8]
Items compared: [8, 2] => swapped [2, 8]
Items compared: [8, 7] => swapped [7, 8]
Items compared: [8, 9] => not swapped
Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ]
Items compared: [1, 4] => not swapped
Items compared: [4, 6] => not swapped
Items compared: [6, 0] => swapped [0, 6]
Items compared: [6, 3] => swapped [3, 6]
Items compared: [6, 5] => swapped [5, 6]
Items compared: [6, 2] => swapped [2, 6]
Items compared: [6, 7] => not swapped
Items compared: [7, 8] => not swapped
Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ]
Items compared: [1, 4] => not swapped
Items compared: [4, 0] => swapped [0, 4]
Items compared: [4, 3] => swapped [3, 4]
Items compared: [4, 5] => not swapped
Items compared: [5, 2] => swapped [2, 5]
Items compared: [5, 6] => not swapped
Items compared: [6, 7] => not swapped
Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [1, 0] => swapped [0, 1]
Items compared: [1, 3] => not swapped
Items compared: [3, 4] => not swapped
Items compared: [4, 2] => swapped [2, 4]
Items compared: [4, 5] => not swapped
Items compared: [5, 6] => not swapped
Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ]
Items compared: [0, 1] => not swapped
Items compared: [1, 3] => not swapped
Items compared: [3, 2] => swapped [2, 3]
Items compared: [3, 4] => not swapped
Items compared: [4, 5] => not swapped
Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ]
Items compared: [0, 1] => not swapped
Items compared: [1, 2] => not swapped
Items compared: [2, 3] => not swapped
Items compared: [3, 4] => not swapped
Output Array: [0 1 2 3 4 5 6 7 8 9 ]
#Python Code for Tower of Hanoi MAX = 10 list = [1, 8, 4, 6, 0, 3, 5, 2, 7, 9] def display(): print("[", end="") # navigate through all items for i in range(MAX): print(list[i], end=" ") print("]") def bubbleSort(): swapped = False # loop through all numbers for i in range(MAX - 1): swapped = False # loop through numbers falling ahead for j in range(MAX - 1 - i): print("Items compared: [", list[j], ", ", list[j + 1], "] ", end="") # check if next number is lesser than the current number # swap the numbers. # (Bubble up the highest number) if list[j] > list[j + 1]: temp = list[j] list[j] = list[j + 1] list[j + 1] = temp swapped = True print("=> swapped [", list[j], ", ", list[j + 1], "]") else: print("=> not swapped") # if no number was swapped, the array is sorted now, break the loop if not swapped: break print("Iteration", (i + 1), "#: ", end="") display() print("Input Array: ", end="") display() print() bubbleSort() print("\nOutput Array: ", end="") display()

输出

Input Array: [1 8 4 6 0 3 5 2 7 9 ]
Items compared: [ 1 ,  8 ] => not swapped
Items compared: [ 8 ,  4 ] => swapped [ 4 ,  8 ]
Items compared: [ 8 ,  6 ] => swapped [ 6 ,  8 ]
Items compared: [ 8 ,  0 ] => swapped [ 0 ,  8 ]
Items compared: [ 8 ,  3 ] => swapped [ 3 ,  8 ]
Items compared: [ 8 ,  5 ] => swapped [ 5 ,  8 ]
Items compared: [ 8 ,  2 ] => swapped [ 2 ,  8 ]
Items compared: [ 8 ,  7 ] => swapped [ 7 ,  8 ]
Items compared: [ 8 ,  9 ] => not swapped
Iteration 1 #: [1 4 6 0 3 5 2 7 8 9 ]
Items compared: [ 1 ,  4 ] => not swapped
Items compared: [ 4 ,  6 ] => not swapped
Items compared: [ 6 ,  0 ] => swapped [ 0 ,  6 ]
Items compared: [ 6 ,  3 ] => swapped [ 3 ,  6 ]
Items compared: [ 6 ,  5 ] => swapped [ 5 ,  6 ]
Items compared: [ 6 ,  2 ] => swapped [ 2 ,  6 ]
Items compared: [ 6 ,  7 ] => not swapped
Items compared: [ 7 ,  8 ] => not swapped
Iteration 2 #: [1 4 0 3 5 2 6 7 8 9 ]
Items compared: [ 1 ,  4 ] => not swapped
Items compared: [ 4 ,  0 ] => swapped [ 0 ,  4 ]
Items compared: [ 4 ,  3 ] => swapped [ 3 ,  4 ]
Items compared: [ 4 ,  5 ] => not swapped
Items compared: [ 5 ,  2 ] => swapped [ 2 ,  5 ]
Items compared: [ 5 ,  6 ] => not swapped
Items compared: [ 6 ,  7 ] => not swapped
Iteration 3 #: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [ 1 ,  0 ] => swapped [ 0 ,  1 ]
Items compared: [ 1 ,  3 ] => not swapped
Items compared: [ 3 ,  4 ] => not swapped
Items compared: [ 4 ,  2 ] => swapped [ 2 ,  4 ]
Items compared: [ 4 ,  5 ] => not swapped
Items compared: [ 5 ,  6 ] => not swapped
Iteration 4 #: [0 1 3 2 4 5 6 7 8 9 ]
Items compared: [ 0 ,  1 ] => not swapped
Items compared: [ 1 ,  3 ] => not swapped
Items compared: [ 3 ,  2 ] => swapped [ 2 ,  3 ]
Items compared: [ 3 ,  4 ] => not swapped
Items compared: [ 4 ,  5 ] => not swapped
Iteration 5 #: [0 1 2 3 4 5 6 7 8 9 ]
Items compared: [ 0 ,  1 ] => not swapped
Items compared: [ 1 ,  2 ] => not swapped
Items compared: [ 2 ,  3 ] => not swapped
Items compared: [ 3 ,  4 ] => not swapped

Output Array: [0 1 2 3 4 5 6 7 8 9 ]