- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐进分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈和队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 哈希表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树的遍历
- DSA - 二叉搜索树
- DSA - AVL 树
- DSA - 红黑树
- DSA - B 树
- DSA - B+ 树
- DSA - 伸展树
- DSA - 字典树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 汉诺塔问题(使用递归)
- DSA - 使用递归计算斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大-最小问题
- DSA - Strassen 矩阵乘法
- DSA - Karatsuba 算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - Prim 最小生成树
- DSA - Kruskal 最小生成树
- DSA - Dijkstra 最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止日期的作业排序
- DSA - 最优合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall 算法
- DSA - 0-1 背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似算法)
- 随机算法
- DSA - 随机算法
- DSA - 随机快速排序算法
- DSA - Karger 最小割算法
- DSA - Fisher-Yates 洗牌算法
- DSA 有用资源
- DSA - 问答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
汉诺塔问题(使用递归)
汉诺塔
汉诺塔是一个数学游戏,由三个塔(桩)和多个环组成,如下图所示:
这些环大小不同,按升序排列堆叠,即较小的环放在较大的环上面。该游戏的其他变体中,圆盘的数量会增加,但塔的数量保持不变。
规则
任务是将所有圆盘移动到另一个塔,而不违反排列顺序。汉诺塔游戏需要遵循以下规则:
- 在任何给定时间,只能在塔之间移动一个圆盘。
- 只能移动“顶部”的圆盘。
- 较大的圆盘不能放在较小的圆盘上面。
以下是使用三个圆盘解决汉诺塔游戏的动画演示。
包含 n 个圆盘的汉诺塔游戏最少需要 2n−1 步才能解决。此演示显示,包含 3 个圆盘的游戏需要 23 - 1 = 7 步。
算法
要编写汉诺塔游戏的算法,首先我们需要学习如何使用较少的圆盘(例如 1 或 2)来解决此问题。我们将三个塔分别命名为 源、目标和 辅助(仅用于帮助移动圆盘)。如果只有一个圆盘,则可以轻松地将其从源塔移动到目标塔。
如果有 2 个圆盘:
- 首先,我们将较小的(顶部)圆盘移动到辅助塔。
- 然后,我们将较大的(底部)圆盘移动到目标塔。
- 最后,我们将较小的圆盘从辅助塔移动到目标塔。
因此,现在我们可以设计一个用于解决包含两个以上圆盘的汉诺塔游戏的算法。我们将圆盘堆栈分成两部分。最大的圆盘(第 n 个圆盘)在一部分,所有其他(n-1)个圆盘在另一部分。
我们的最终目标是从源塔将第 n 个圆盘移动到目标塔,然后将所有其他(n-1)个圆盘放在它上面。我们可以想象以递归的方式对所有给定的圆盘集应用相同的操作。
需要遵循的步骤:
Step 1 − Move n-1 disks fromsource
toaux
Step 2 − Move nth disk fromsource
todest
Step 3 − Move n-1 disks fromaux
todest
汉诺塔游戏的递归算法可以如下所示:
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> void hanoi(int n, char from, char to, char via) { if(n == 1){ printf("Move disk 1 from %c to %c\n", from, to); } else{ hanoi(n-1, from, via, to); printf("Move disk %d from %c to %c\n", n, from, to); hanoi(n-1, via, to, from); } } int main() { int n = 3; char from = 'A'; char to = 'B'; char via = 'C'; //calling hanoi() method hanoi(n, from, via, to); }
#include <iostream> using namespace std; void hanoi(int n, char from, char to, char via) { if(n == 1){ cout<<"Move disk 1 from "<<from<<" to "<<to<<endl; } else{ hanoi(n-1, from, via, to); cout<<"Move disk "<<n<<" from "<<from<<" to "<<to<<endl; hanoi(n-1, via, to, from); } } int main() { int n = 3; char from = 'A'; char to = 'B'; char via = 'C'; //calling hanoi() method hanoi(n, from , via, to); }
import java.util.*; public class Demo { public static void hanoi(int n, String from, String to, String via) { if(n == 1){ System.out.println("Move disk 1 from " + from + " to " + to); } else{ hanoi(n-1, from, via, to); System.out.println("Move disk " + n + " from " + from + " to " + to); hanoi(n-1, via, to, from); } } public static void main(String[] args) { int n = 3; String from = "A"; String to = "B"; String via = "C"; //calling hanoi() metod hanoi(n, from, via, to); } }
def hanoi(n, f, to, via): if n == 1: print("Move disk 1 from",f,"to",to); else: hanoi(n-1, f, via, to) print("Move disk",n,"from",f,"to",to); hanoi(n-1, via, to, f) n = 3 f = 'A' to = 'B' via = 'C' hanoi(n, f, via, to)
输出
Move disk 1 from A to C Move disk 2 from A to B Move disk 1 from C to B Move disk 3 from A to C Move disk 1 from B to A Move disk 2 from B to C Move disk 1 from A to C
广告