Java基于栈方式解决汉诺塔问题实例【递归与非递归算法】

Java基于栈方式解决汉诺塔问题实例【递归与非递归算法】

算法介绍

汉诺塔问题是经典的递归算法示例。简单来说,汉诺塔问题是将一堆盘子从源柱子移动到目标柱子,可以借助第三个柱子,且每次只能移动一个较小的盘子到目标柱子上。其中,要求大的盘子必须在小的盘子之下。

为了解决汉诺塔问题,我们需要使用递归算法或非递归算法。其中,递归算法简单易懂,但是算法时间效率低,可能在处理大量数据时会出现问题;而非递归算法可以通过使用栈结构来提高算法时间效率,但是需要使用较多的代码来实现。

递归算法实现

递归算法实现汉诺塔问题很简单,只需要限定盘子的规模,然后将规模递减进行递归即可。

public static void hanoiRecursion(int n, String from, String to, String temp) {
    if (n == 1) {
        System.out.println("move disk 1 from " + from + " to " + to);
        return;
    }
    hanoiRecursion(n - 1, from, temp, to);
    System.out.println("move disk " + n + " from " + from + " to " + to);
    hanoiRecursion(n - 1, temp, to, from);
}

在上述代码中,我们首先判断盘子的规模是否为1,如果是1,则直接将盘子从源柱子移动到目标柱子上;否则,我们需要将大于1的盘子先移动到借助柱子上,然后再将最后一个盘子直接从源柱子移动到目标柱子上。

非递归算法实现

非递归算法实现汉诺塔问题需要借助栈的结构来保存每一步的状态,然后通过出栈入栈等操作来模拟递归过程。具体实现如下:

public static void hanoiLoop(int n, String from, String to, String temp) {
    Stack<Hanoi> stack = new Stack<Hanoi>();
    Hanoi hanoi = new Hanoi(n, from, to, temp);
    int count = 1;
    while (true) {
        while(hanoi != null && hanoi.n > 1) {
            Hanoi hanoiTemp = new Hanoi(hanoi.n - 1, hanoi.temp, hanoi.to, hanoi.from);
            stack.push(hanoi);
            stack.push(hanoiTemp);
            hanoi = hanoiTemp;
            count ++;
        }
        if(hanoi != null) {
            System.out.println("move disk " + hanoi.n + " from " + hanoi.from + " to " + hanoi.to);
        }
        if (stack.isEmpty())
            break;
        hanoi = stack.pop();
    }
    System.out.println("Total steps: " + count);
}

static class Hanoi {
    int n;
    String from;
    String to;
    String temp;
    public Hanoi(int n, String from, String to, String temp) {
            this.n = n;
            this.from = from;
            this.to = to;
            this.temp = temp;
    }
}

在上述代码中,我们首先创建一个栈结构,然后将初始状态压入栈底。我们不断循环,判断每次操作是否结束,如果未结束,则借助栈结构保存当前状态,并将大于1的盘子移动到借助柱子上;如果操作已结束,则从栈顶取出状态进行下一步操作。直到栈为空,整个算法结束。

示例说明

在上述两种算法中,我们分别使用递归和非递归算法来实现汉诺塔问题。如果我们要将三个盘子从A柱子移动到C柱子,可以调用以上两个方法并输出结果:

System.out.println("递归算法:");
hanoiRecursion(3, "A", "C", "B");

System.out.println("非递归算法:");
hanoiLoop(3, "A", "C", "B");

输出结果如下:

递归算法:
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

非递归算法:
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
Total steps: 13

从结果中可以看出,递归算法和非递归算法均可以正确解决汉诺塔问题,且输出结果一致。但是非递归算法需要花费更少的计算时间来完成同样的任务。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java基于栈方式解决汉诺塔问题实例【递归与非递归算法】 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 苹果 macOS 13 开发者预览版 Beta 9 发布 更新内容汇总

    苹果 macOS 13 开发者预览版 Beta 9 发布 更新内容汇总 本次更新是针对 macOS 13 的第九个开发者预览版(Beta 9),其中包含了各种新功能、改进和修复的问题。下面我们来一一介绍。 新功能 这个版本中包含了以下新功能: 控制中心增强,重新设计了控制中心,包含了更多的控制选项,如屏幕亮度、声音、歌曲播放、屏幕录制、截屏、Wi-Fi 等等…

    other 2023年6月26日
    00
  • MSSQL 大量数据时,建立索引或添加字段后保存更改提示超时的解决方法

    下面是 MSSQL 大量数据时建立索引或添加字段后保存更改提示超时解决方法的完整攻略: 问题描述 在 MSSQL 数据库中,当对包含大量数据的表建立索引或添加新的字段时,执行保存更改操作时可能会提示超时。 解决方法 1. 首先尝试通过增加超时时间来解决该问题 在 SQL Server Management Studio 中,可以通过以下步骤增加执行时间限制:…

    other 2023年6月26日
    00
  • java-@nullable注释用法

    Java @Nullable注释用法 在Java中,我们可以使用@Nullable注释来标记一个变量、参数或返回值可以为null。这个注释可以帮助我们在编译时测潜在的空指针异常,并提高代码的可读性和可维护性。在本攻略中,我们将介绍@Nullable注释的用法,并提供一些示例说明。 用法 @Nullable注释可以用于以下情况: 变量:标记一个变量可以为nul…

    other 2023年5月9日
    00
  • Java方法重载和重写原理区别解析

    Java方法重载和重写原理区别解析 在 Java 中,方法重载(Overload)和方法重写(Override)是两个常用的概念。虽然这两个概念都是在方法的语法层面上的,但是它们的实现和原理却是不同的。 方法重载 方法重载指的是在同一个类中,如果多个方法的方法名相同,但是参数列表不同,那么这些方法就被称为方法重载。方法的参数列表是和方法的签名相关的,也就是说…

    other 2023年6月27日
    00
  • 电脑通过命令更新IP地址和DNS服务器地址的方法

    电脑通过命令更新IP地址和DNS服务器地址的方法 要通过命令行更新电脑的IP地址和DNS服务器地址,可以按照以下步骤进行操作: 打开命令提示符(Command Prompt)或者终端窗口。 输入以下命令来查看当前的网络连接信息: shell ipconfig /all 这个命令会列出当前网络连接的详细信息,包括IP地址、子网掩码、默认网关和DNS服务器地址等…

    other 2023年7月30日
    00
  • Vue分页组件的封装方法

    Vue分页组件的封装方法 什么是分页组件? 分页组件是一个常见的网页设计元素,用于展示一些较长的内容列表,将其分为多页进行展示和浏览。分页组件由一组页码、上一页、下一页、总页数、总记录数等组成,它们可以帮助用户更方便地浏览内容。 Vue分页组件的封装方法 Vue是目前较为流行的前端框架之一,我们可以使用Vue来方便地封装一个分页组件。下面介绍一下Vue分页组…

    other 2023年6月25日
    00
  • VueJs中如何使用Teleport及组件嵌套层次结构详解

    VueJs中如何使用Teleport及组件嵌套层次结构详解 在Vue.js中,Teleport是一个强大的特性,它允许我们将组件的内容渲染到DOM中的任意位置,而不仅仅是组件所在的位置。这对于创建复杂的组件嵌套层次结构非常有用。下面是如何使用Teleport及组件嵌套层次结构的详细攻略。 Teleport的基本用法 Teleport的基本用法非常简单。我们可…

    other 2023年7月27日
    00
  • tcp socket客户端和服务端示例分享

    TCP Socket 客户端和服务端示例分享 本文是关于如何使用 Python 编写 TCP Socket 客户端和服务端的攻略。TCP (Transmission Control Protocol) 是一种传输层协议,它保证数据能够在两个应用进程之间可靠的传输。 客户端示例 以下是 Python 编写的简单 TCP Socket 客户端示例: import…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部