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

yizhihongxing

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日

相关文章

  • 辐射4出避免所后无法移动的解决方法

    下面是“辐射4出避免所后无法移动的解决方法”的完整攻略。 问题描述 在玩“辐射4”时,有时候会出现因为误入禁区或其他原因而无法返回原先所在地点的情况,导致角色无法行动,无法玩游戏。 解决方法 出现以上情况时,可以采取以下步骤解决: 步骤一:使用控制台命令 暂停游戏,按下“~”键打开控制台。 输入以下命令: tcl 这个命令会关闭角色的碰撞检测,这样就可以通过…

    other 2023年6月27日
    00
  • iOS12 beta6更新了什么 iOS12beta6更新内容及新Bug一览

    iOS 12 Beta 6 更新内容及新 Bug 一览 更新内容 iOS 12 Beta 6 是苹果公司为其移动操作系统 iOS 12 推出的第六个测试版本。以下是该版本的一些更新内容: 性能优化:iOS 12 Beta 6 对系统性能进行了优化,提升了整体的响应速度和流畅度。这意味着在使用 iOS 12 Beta 6 的设备上,用户可以更快地打开应用程序、…

    other 2023年8月3日
    00
  • 前端必会的图片懒加载(三种方式)

    前端图片懒加载技术是指在用户需要访问图片的时候才加载,而在用户未需要访问的时候不加载,以此达到优化页面性能的目的。在本篇攻略中,我们将介绍三种常见的前端图片懒加载方法。 一、使用IntersectionObserver实现懒加载 Intersection Observer是Web API的一部分,它可以观察一个元素是否出现在视窗中。我们可以通过监听元素和视窗…

    other 2023年6月25日
    00
  • python基于朴素贝叶斯算法的情感分析

    Python基于朴素贝叶斯算法的情感分析 情感分析是一种自然语言处理技术,用于确定文本中的情感倾向。本文将介绍如何使用Python和朴素贝叶斯算法实现情感分析,并提供两个示例说明。 数据集 情感分析需要标注好的数据集,用于训练分类器。常见的数据集有IMDB电影评论数据集、亚马逊商品评论数据集等。本文将使用IMDB电影评论数据集,该数据集包50000条电影评论…

    other 2023年5月8日
    00
  • 部署RemoteApp实现应用程序的远程调用

    关于部署RemoteApp实现应用程序的远程调用,我为你提供如下攻略: 什么是RemoteApp? RemoteApp是Windows Server为用户提供的一项强大的服务,它使得用户可以在本地PC上运行远程主机上的应用程序,同时在本地PC上显示应用程序的窗口和进行相关的操作。 部署RemoteApp 以下是具体的操作步骤: 部署远程桌面服务 远程App服…

    other 2023年6月25日
    00
  • 在RecyclerView中实现button的跳转功能

    当在RecyclerView中需要实现按钮的跳转功能时,可以按照以下步骤进行操作: 在RecyclerView的Adapter中,为每个列表项添加一个按钮。可以在列表项的布局文件中添加一个Button控件,并为其设置一个唯一的ID。 示例代码: <Button android:id=\"@+id/button_item\" andr…

    other 2023年8月23日
    00
  • js中var、let、const之间的区别

    JavaScript中var、let、const之间的区别 在JavaScript中,var、let和const是用于声明变量的关键字。它们之间有一些重要的区别,包括作用域、变量提升和可变性等方面。 var var是ES5中引入的关键字,用于声明变量。它具有以下特点: 函数作用域:var声明的变量的作用域是函数级别的,即在函数内部声明的变量在函数外部是不可访…

    other 2023年8月21日
    00
  • 深入了解python全局变量,局部变量和命名空间

    深入了解 Python 全局变量、局部变量和命名空间攻略 在 Python 中,全局变量、局部变量和命名空间是非常重要的概念。理解它们的作用和区别对于编写高效、可维护的代码至关重要。本攻略将详细介绍这些概念,并提供示例来帮助理解。 1. 全局变量 全局变量是在整个程序中都可以访问的变量。它们在任何函数内部都可以使用,而不需要进行额外的声明或传递。在 Pyth…

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