递归实现与main():

/*------------------------------------------------------
汉诺塔主要是有三个塔座X,Y,Z,要求将从小到大编号为 1,2.....n 的
圆盘从X移动到塔座Z上,要求(1):每次只能移动一个圆盘(2):圆盘可以插到X,Y,Z中任一塔座上(3):任何时候不能将一个较大的圆盘压在较小的圆盘之上初始:所有圆盘都在 X 塔座,并且最大的圆盘在最底部,然后是次大的;结束:所有圆盘都在 Z 塔座,并且最大的圆盘在最底部,然后是次大的;
------------------------------------------------------*/
#include <iostream>
#include <ctime>  // time()
using namespace std;
/*-----------------------------------------------------------
前置条件: n > 0
后置条件: 输出将n个圆盘从源塔座(orig)移动到目的塔座(dest)的步骤,临时塔座(temp)用于临时存放。
算法(递归):n == 1时,把盘1从源移动到目的地n > 1时,1)将n-1个圆盘(每次移动一个)从源移动到临时塔座2)将盘n从源移动到目的地3)将n-1个圆盘(每次移动一个)从临时塔座移动到目的塔座
时间复杂度: wotstTime(n) 是 O(2^n).
空间复杂度: worstSpace(n) 是 O(n).
-----------------------------------------------------------*/
void move(int n, char orig[], char dest[], char temp[])
{static char ori = 'X', tem = 'Y', des = 'Z', ch;  // 三个塔座static int num = 0, length = n;        // num记录移动步数, length保存圆盘数目if (n <= 0){   // 处理参数传递错误cout << "The value is error!\n";return;}if (n == 1){   // 通用策略: n == 1时情况dest[n-1] = orig[n-1];num++;cout << num << ") Disc " << orig[n-1] << ": "<< ori << "-->" << des << endl;}else{           // 通用策略: n > 1时情况ch = des; des = tem; tem = ch;move(n-1, orig, temp, dest);ch = des; des = tem; tem = ch;dest[n-1] = orig[n-1];num++;cout << num << ") Disc " << orig[n-1] << ": "<< ori << "-->" << des << endl;ch = ori; ori = tem; tem = ch;move(n-1, temp, dest, orig);ch = ori; ori = tem; tem = ch;}if (dest[length] != '\0')dest[length] = '\0';
}
// move中声明的局部变量为静态的,这样在使用递归调用的move函数里只在第一次定义时初始化;
// 塔座名ori、tem、des要随着递归调用时参数的传递而变化,递归调用结束后应该及时恢复;
// n为圆盘数目,塔座结构采用C-styel字符串,因注意字符串末尾要有'\0';void movecopy(int, char [], char [], char []);
int main()
{long start_time, finish_time, elapsed_time1, elapsed_time2;const int N = 5;       // 圆盘数目为 N-1char orig[N] = "abcd", temp[N], dest[N];// 计算move()函数运行了多少时间(time()的返回值类型为long)cout << "move::orig = " << orig << endl;start_time = time(NULL);move(N-1, orig, dest, temp);finish_time = time(NULL);elapsed_time1 = finish_time - start_time;cout << "move::dest = " << dest << endl << endl;// 计算movecopy()函数运行了多少时间cout << "movecopy::orig = " << orig << endl;start_time = time(NULL);movecopy(N-1, orig, dest, temp);finish_time = time(NULL);elapsed_time2 = finish_time - start_time;cout << "movecopy::dest = " << dest << endl << endl;// move()和movecopy()运行时间比较cout << "move::The elapsed time was " << elapsed_time1<< " senonds." << endl;cout << "movecopy::The elapsed time was " << elapsed_time2<< " senonds." << endl;return 0;
}

迭代实现:

/*--------------------------------------------------------------
前置条件: n > 0
后置条件: 输出将n个圆盘从源塔座(orig)移动到目的塔座(dest)的步骤,临时塔座(temp)用于临时存放。
算法(迭代): 1)确定哪一个圆盘要移动。a.移动次数: c(n) = 2^n -1;b.m为n位的二进制数,则m的取值范围为0~2^n -1。规律:让m每次递增1,可以发现,m中最高一位的刚刚由0变为1的位置的位置编号,和即将要移动的盘子编号有确定关系。 2)这个盘子往哪个塔座上移动。 a.n为奇数时,奇数编号圆盘按顺时针移动(X->Y->Z->X),偶数编号圆盘按逆时针移动(X->Z->Y->X);b.n为偶数时,偶数编号圆盘按顺时针移动(X->Y->Z->X),奇数编号圆盘按逆时针移动(X->Z->Y->X);
--------------------------------------------------------------*/
void movecopy(int n, char orig[], char dest[], char temp[])
{char ori[] = "orig(X)", tem[] = "temp(Y)", des[] = "dest(Z)";// 三个塔座int num = 0;     // num记录移动步数int m1[32], m2[32], tempnum, i, j, k;// m1、m2数组存储 n的二进制bit位,且 n(m2对应) = n(m1对应) + 1;// i、j分别为m1、m2中存储n值要求的二进制的最小bit数;// k+1 为求得的盘子编号int x = n, y = 0, z = 0;// x、y、z分别跟踪三个塔座当前的圆盘数目if (n == 0){      // 处理参数传递错误cout << "The value is error!\n";return;}// 保存orig中元素到ch[32],然后反转orig塔座中圆盘的顺序// (如:'a'在orig中第一个位置,但是 'a' 也在塔座的最上方--第n-1个位置)char ch[32];for (i = 0; i < n; i++)ch[i] = orig[i];for (int length = n-1, i = 0; i < n; i++, length--){orig[i] = ch[length];}ch[n] = '\0';dest[n] = '\0';temp[n] = '\0';for (int l = 0; l < (1<<n)-1; l++)  // 移动次数:2^n-1 既是 (1<<n)-1{// 1)确定哪一个圆盘要移动(求 k+1 的值)tempnum = l;for (i = 0; tempnum != 1 && tempnum != 0; i++){m1[i] = tempnum%2; tempnum = tempnum/2;}m1[i] = tempnum;tempnum = l+1;for (j = 0; tempnum != 1 && tempnum != 0; j++){m2[j] = tempnum%2; tempnum = tempnum/2;}m2[j] = tempnum;if (j > i) k = j;elsefor (k = j; m2[k] == m1[k]; k--) ;num++;cout << num << ") Disc " << ch[k] << ": ";// 2)这个盘子往哪个塔座上移动。if (((n % 2 == 0 && ((k+1)%2 == 0))) ||    // (n为偶数,偶数编号圆盘顺时针移动)((n % 2 != 0) && ((k+1)%2 != 0))){ // (n为奇数,奇数编号圆盘顺时针移动)for (i = 0; ch[k] != orig[i] && i < x; i++) ;if ((i > 0 && i < x) || (i == 0 && orig[i] == ch[k])){dest[y] = orig[i];y++; x--; cout << ori << "-->" << des;orig[i] = '\0';}else{    // (如果在orig塔座没有找到需要圆盘)for (i = 0; ch[k] != dest[i] && i < y; i++) ;if ((i > 0 && i < y) || (i == 0 && dest[i] == ch[k])){temp[z] = dest[i];z++; y--; cout << des << "-->" << tem;dest[i] = '\0';}else{  // (如果在orig和dest塔座都没有找到需要圆盘)for (i = 0; ch[k] != temp[i] && i < z; i++) ;if ((i > 0 && i < z) || (i == 0 && temp[i] == ch[k])){orig[x] = temp[i];x++; z--; cout << tem << "-->" << ori;temp[i] = '\0';}}}}else{ // (n为奇数,偶数编号圆盘逆时针移动)(n为偶数,奇数编号圆盘逆时针移动)for (i = 0; ch[k] != orig[i] && i < x; i++) ;if ((i > 0 && i < x) || (i == 0 && orig[i] == ch[k])){temp[z] = orig[i];z++; x--; cout << ori << "-->" << tem;orig[i] = '\0';}else{ // (如果在orig塔座没有找到需要圆盘)for (i = 0; ch[k] != dest[i] && i < y; i++) ;if ((i > 0 && i < y) || (i == 0 && dest[i] == ch[k])){orig[x] = dest[i];x++; y--; cout << des << "-->" << ori;dest[i] = '\0';}else{  // (如果在orig和dest塔座都没有找到需要圆盘)for (i = 0; ch[k] != temp[i] && i < z; i++) ;if ((i > 0 && i < z) || (i == 0 && temp[i] == ch[k])){dest[y] = temp[i];y++; z--; cout << tem << "-->" << des;temp[i] = '\0';}}}}cout << endl;}// 保存dest中元素到ch[32],然后反转dest塔座中圆盘的顺序for (i = 0; i < n; i++)ch[i] = dest[i];for (int length = n-1, i = 0; i < n; i++, length--){dest[i] = ch[length];}
}

运行结果:

我把main()中变动为 const int N = 15; 时,move()运行了 44 seconds,而movecopy()运行了 80 seconds..

这个递归版本明显好于迭代版本

递归3: 汉诺塔的递归与迭代实现相关推荐

  1. 递归(汉诺塔和递归求和)

    程序调用自身的编程技巧称为递归( recursion).递归作为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一 ...

  2. 数据结构与算法—递归算法(从阶乘、斐波那契到汉诺塔的递归图解)

    目录 递归介绍 递归求阶乘 递归求斐波那契 递归解决汉诺塔 总结 递归介绍 递归:就是函数自己调用自己. 子问题须与原始问题为同样的事,或者更为简单: 递归通常可以简单的处理子问题,但是不一定是最好的 ...

  3. Py:递归求解汉诺塔,简单的几行编程可以搞定很高层的三柱汉诺塔游戏

    Py:递归求解汉诺塔,简单的几行编程可以搞定很高层的三柱汉诺塔游戏 目录 输出结果 核心代码 输出结果 核心代码 def hanoi(n,x,y,z):if n==1:print(x,'--→',z) ...

  4. Python递归实现汉诺塔

    Python递归实现汉诺塔: def f3(n,x,y,z): if(n==1):print(x,'--->',z)else:f3(n-1,x,z,y)print(x,'--->',z)f ...

  5. labview求n阶乘的和_递归算法(从阶乘、斐波那契到汉诺塔的递归图解)

    递归介绍 递归:就是函数自己调用自己. 子问题须与原始问题为同样的事,或者更为简单: 递归通常可以简单的处理子问题,但是不一定是最好的. 对于递归要分清以下概念: 自己调用自己 递归通常不在意具体操作 ...

  6. 【恋上数据结构】递归(函数调用过程、斐波那契数列、上楼梯、汉诺塔、递归转非递归、尾调用)

    递归(Recursion) 什么是递归? 函数的调用过程(栈空间) 函数的递归调用过程 递归实例分析(1 + 2 + 3 + ... + 100 的和) 递归的基本思想.使用套路 斐波那契数列 fib ...

  7. c语言递归汉诺塔次数,c语言递归解决汉诺塔参数变化的疑惑

    c语言递归解决汉诺塔参数变化的疑惑 答案:3  信息版本:手机版 解决时间 2020-04-05 14:20 已解决 2020-04-05 10:49 #include void main() {vo ...

  8. c语言递归解决汉诺塔问题

    c语言递归解决汉诺塔问题 参考文章: (1)c语言递归解决汉诺塔问题 (2)https://www.cnblogs.com/didiaoxiaoguai/p/6686407.html 备忘一下.

  9. python面向过程实践汉诺塔_递归汉诺塔-和递归汉诺塔相关的内容-阿里云开发者社区...

    多柱汉诺塔最优算法设计探究 多柱汉诺塔最优算法设计探究 引言 汉诺塔算法一直是算法设计科目的最具代表性的研究问题,本文关注于如何设计多柱汉诺塔最优算法的探究.最简单的汉诺塔是三个柱子(A.B.C),因 ...

  10. c语言 统计数量用count_C语言编程学习之递归实现汉诺塔图解!还有零基础入门视频~...

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

最新文章

  1. 模板 - 输入输出优化
  2. Exception经验之谈,万万没想到被很多团队采纳!
  3. SAP固定资产期初导入检查
  4. nyoj-754--黑心医生
  5. Ado.net 创建DataTable
  6. 【Linux】一步一步学Linux——虚拟机简介和系统要求(04)
  7. 十二五期间三网融合将有实质性进展
  8. Mysql| Mysql函数,聚集函数的介绍与使用(Lower,Date,Mod,AVG,...)
  9. 在SharePoint网站中访问Webservice被拒绝的解决方法
  10. Android-利用LinearGradient实现文字一闪一闪
  11. win10默认壁纸_仅4M!微软出品的壁纸软件,让桌面每天都不一样!
  12. 测试用例(教室丶椅子)
  13. IM方案技术调研报告
  14. Leetcode 858. 镜面反射 Python解法
  15. 《第一行代码》学习笔记——第1章 开始启程,你的第一行Android代码
  16. 第三人称计算机获奖感言,玄彬获奖感言感谢女友孙艺珍 惹众网友羡慕
  17. ajax请求去获取base64_php如何获取ajax提交过来的经过base64处理后的图片
  18. 走向5G:面对困难,展望未来
  19. python基础知识三 字典-dict + 菜中菜
  20. Linux中的shell到底是啥,它和bash的关系是什么?

热门文章

  1. Facebook速推帖子和Facebook广告有什么区别
  2. 06_张孝祥_多线程_ThreadLocal类及应用技巧
  3. 巨杉数据库5.0携手同方软银促进金融科技创新
  4. 如何计算当地的中央子午线?
  5. python 123 io网站答题如果最小化会有提示吗_爬虫进阶教程:百万英雄答题辅助系统...
  6. 亚信科技运维实习生(笔试)
  7. css逐渐消失,css如何实现渐渐消失
  8. 大数据学习之Spark-core常用代码示例
  9. Received status code 400 from server: Bad Request解决方案
  10. android人脸解锁亮屏,EMUI 8.0升级加入全新人脸解锁 抬腕亮屏功能:快来看看如何开启...