递归,其实就是函数调用其本身来实现某些算法。
        在非必要情况下,尽可能不用递归,而是使用迭代来进行处理。即,使用for、while、foreach等循环来取代递归。
        迭代使用的是循环结构,递归使用的是选择结构。
        每个递归定义必须至少有一个条件,当满足条件时递归不再进行。
        递归的优点:结构更清晰,代码更简洁,更容易让人理解,从而减少代码的阅读时间。
下面是两个经典的问题,一个经典的汉诺塔问题,是递归入门的基础,一个八皇后问题,一般是回溯算法的经典例题,在这里使用递归解决。


问题一:汉诺塔问题

问题描述:在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片,一次只移动一片,不管在哪根针上,小片必在大片上面。当所有的金片都从梵天穿好的那根针上移到另外一概针上时,世界就将在一声霹雳中消灭,梵塔、庙宇和众生都将同归于尽。

        如上图所示,此时我们需要把A移动到C,需要写一个算法来解决这个问题。
        我们可以考虑,此时如果我们把A上面的63块金片移动到了B上,此时A上只有最下面的最大的那片金片,移动一次,把它移动到C上,然后这个时候,由于C上的金片最大,所以不管放哪片金片都没问题。
        第二步,把B上的62块金片移动到A上,B上只剩下C,这个时候又是只需要一次,就能移动成功,此时A上有62块金片,B上什么都没有,C上有已排列好的最大的两块金片。
        以此类推,移动n次后,就能移动完毕,把最初A上的64片金片全部移动到C上。

于是有
f(n + 1) = 2*f(n) + 1 -> [f(n + 1) + 1] = 2*[f(n) + 1]
f(1) = 1, -> f(n) + 1 = (1 + 1)^n -> f(n) = 2^n - 1。
f(64)= 2^64 - 1 = 18446744073709551615  

以下为汉诺塔的递归代码:

class Hanoi
{/// <summary>/// 移动汉诺塔盘子问题,得到移动的次数/// </summary>/// <param name="n">汉诺塔的层数</param>public void GetMoveCount(int n){if (n <= 0)throw new Exception("层数出错!");int[] num = new int[n];for (int i = 1; i <= n; i++)num[i - 1] = i;Move(n, 'X', 'Y', 'Z');}private void Move(int n, char x, char y, char z){if (1 == n){Console.WriteLine("将第{0}个盘子从{1}轴移动到{2}轴上", n, x, z);}else{Move(n - 1, x, z, y);                                                       //将n-1个盘子从x轴移动到y轴上,把z轴作为辅助轴Console.WriteLine("将第{0}个盘子从{1}轴移动到{2}轴上", n, x, z);            //将x轴的最后一个盘子移动到z轴上Move(n - 1, y, x, z);                                                       //将剩余的n-1个盘子从y轴移动到z轴上,把x轴作为辅助轴}}
}

问题二:八皇后问题

问题描述:在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行、列和斜线的敌方棋子。比中国象棋里的车强几百倍,比她那没用的老公更是强的飞起(国王只能前后左右斜线走一格)。
        八皇后问题是这样一个问题:将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法?此问题在1848年由棋手马克斯·贝瑟尔提出,岂止是有年头,简直就是有年头,82年的拉菲分分钟被秒的渣都不剩。
        递归,再确定每一行的棋子位置之后往下一行进行放置,直到每一行棋子都放置完毕,然后输出这个棋盘上棋子的放置位置,然后返回到上一行的放置棋子位置,向后遍历,直到遍历完所有每行所有列可以摆放的位置为止。

以下为参考代码:

class EightQueue
{private int count = 0;              //计数器,用于统计可放置的方法的数量public void Solution(int num){int row = num, col = num;int[,] cheers = new int[row, col];//初始化棋盘,为0表示没有放置棋子,为1表示放置了皇后for (int i = 0; i < row; i++)for (int j = 0; j < col; j++)cheers[i, j] = 0;SolutionCore(0, col, cheers);Console.WriteLine("总共有{0}种方法放置八个皇后", count);}/// <summary>/// 遍历找出所有能够放置的方法/// </summary>/// <param name="startRow">起始的行数</param>/// <param name="cols">列数</param>/// <param name="cheers">棋盘</param>private void SolutionCore(int startRow, int cols, int[,] cheers){//创建一个临时棋盘用于存放每一种放置的方法而不影响最初的棋盘int[,] tempCheers = new int[cols, cols];//初始化临时棋盘for (int i = 0; i < cols; i++)for (int j = 0; j < cols; j++)tempCheers[i, j] = cheers[i, j];//如果满足条件,打印棋子放置的位置if (startRow == 8){//因为count从0开始的,所以输出数的时候需要+1Console.WriteLine("第{0}种放置的方法:", count + 1);for (int i = 0; i < cols; i++){for (int j = 0; j < cols; j++)Console.Write(cheers[i, j] + "  ");Console.WriteLine();}Console.WriteLine();count++;}else{//判断该列的哪个位置可以放置棋子for (int i = 0; i < cols; i++){//如果可以放置棋子,那么进入下一行if (CanPut(startRow, i, tempCheers)){for (int j = 0; j < cols; j++)tempCheers[startRow, j] = 0;tempCheers[startRow, i] = 1;SolutionCore(startRow + 1, cols, tempCheers);}}}}/// <summary>/// 检查当前位置是否可以放置棋子/// </summary>/// <param name="startRow">当前行</param>/// <param name="col">当前列</param>/// <param name="cheers">棋盘</param>/// <returns></returns>private bool CanPut(int startRow, int col, int[,] cheers){int length = cheers.GetLength(0);                 //获取棋盘的行列值,方便下面的计算//创建五个可能性的标志并初始化bool[] flag = new bool[5];for (int i = 0; i < flag.Length; i++){flag[i] = false;}//判断该棋子的一列是否存在其他棋子for (int row = 0; row < length; row++){if (1 == cheers[row, col]){flag[0] = true;break;}}//判断该棋子的左上方是否存在其他棋子for (int i = startRow - 1, j = col - 1; i >= 0 && j >= 0; i--, j--){if (1 == cheers[i, j]){flag[1] = true;break;}}//判断该棋子的右下方是否存在其他棋子for (int i = startRow + 1, j = col + 1; i < length && j < length; i++, j++){if (1 == cheers[i, j]){flag[2] = true;break;}}//判断该棋子的右上方是否存在其他棋子for (int i = startRow - 1, j = col + 1; i >= 0 && j < length; i--, j++){if (1 == cheers[i, j]){flag[3] = true;break;}}//判断该棋子的左下方是否存在其他棋子for (int i = startRow + 1, j = col - 1; i < length && j >= 0; i++, j--){if (1 == cheers[i, j]){flag[4] = true;break;}}//判断当前是否可以放置棋子,如果五个方向都没有其他棋子(flag全部为false),则可以放置for (int i = 0; i < flag.Length; i++){if (flag[i])return false;}return true;}}

数据结构之算法——递归相关推荐

  1. Java 数据结构和算法 - 递归

    Java 数据结构和算法 - 递归 什么是递归 背景:数学归纳法证明 基本递归 printing numbers in any base 它为什么有效 如何工作 递归太多是危险的 树 数值应用 模幂运 ...

  2. Java数据结构和算法 - 递归

    三角数字 Q: 什么是三角数字? A: 据说一群在毕达哥拉斯领导下工作的古希腊的数学家,发现了在数学序列1,3,6,10,15,21,--中有一种奇特的联系.这个数列中的第N项是由第N-1项加N得到的 ...

  3. 数据结构与算法——递归、回溯与分治

    文章目录 1.预备知识 1.1 递归 1.2 回溯 1.3 位运算 2.子集 2.1 题目描述 2.2 解题思路--回溯递归法 2.3 C++实现 2.4 解题思路--位运算法 2.5 位运算实现 3 ...

  4. 数据结构与算法--递归(Recursion Algorithm)

    什么是递归算法? 把规模大的.较难解决的问题变成规模较小的.易解决的同一问题.规模较小的问题又变成规模更小的问题,并且小到一定程度可以直接得出它的解(基本问题),从而得到原来问题的解. 哪时候用递归算 ...

  5. 数据结构与算法——递归、回溯与分治汇总整理

    目录 预备知识:递归函数与回溯算法 例1-a:求子集(medium)(回溯法.位运算法) 例1-b:求子集2(medium)(回溯法) 例1-c:组合数之和2(medium)(回溯法.剪枝) 例2:生 ...

  6. 数据结构与算法--递归(factorial)

    什么是递归? 百度百科上的解释是:程序调用自身的编程技巧称为递归(factorial). 递归是一种应用比较广泛的算法,它通常把一个复杂的问题转化为一个与原问题相似小问题来求解,这样大大的减少了程序的 ...

  7. Java学习手册:(数据结构与算法-递归)一个人爬楼梯,可以一次爬一阶或者两阶,问n层楼梯有多少种爬法?

    算法思想: (1)只有一层楼梯,有1种方法,即 f(1) = 1; (2)有两层楼梯,有2种方法,即 f(2) = 2: (3)有三层楼梯,a.如果第一步爬一层,后面还有两层楼梯未爬,有2种方法,即f ...

  8. python 进制转换_Python数据结构与算法——递归应用之进制转换

    高考加油 在前面的文章中堆栈也用于进制转换(存放余数).而递归也可以用于进制转换,有固定模式循环,并且可以规模越来越小的问题都可以转换成递归 栈与递归之间一定有点联系 整数转换成任意进制 日常运算都是 ...

  9. 数据结构与算法 - 递归回溯(迷宫问题)

    递归的概念 简单说就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码简介 递归的调用机制 递归能解决什么问题 递归需要遵守的重要规则 下面用代码来实现一个迷 ...

  10. Python 数据结构与算法——递归

    所谓递归,其实就是指某一函数--直接或间接--调用自己的操作. 下面将演示一个如何用递归的方式求解某一序列的求和: def S(seq, i=0):if (i == len(seq)): return ...

最新文章

  1. ios玩全民奇迹不显示服务器,全民奇迹关于IOS充值游戏物品不到账公告
  2. Spring Boot + Redis:模拟 10w 人的秒杀抢单!
  3. 插入ts以及判断列是否存在(支持多数据库)
  4. boost::geometry::detail::copy_segments的用法测试程序
  5. 中国广告营销行业资本报告2020
  6. void*和void类型
  7. 一起来学习丨听海华大赛第一名团队聊比赛经验和心得
  8. WIBU-KEY加密狗驱动软件使用说明
  9. yum安装python3
  10. one-stage 目标检测——M2Det源码运行测试
  11. photoshop实现图片更换背景
  12. Flowable深入浅出-14 Flowable-BPMN操作流程之任务完成
  13. Scrapy报错之:Request object has no attribute dont_filter
  14. 2017互联网月饼哪家强?腾讯、阿里、百度、网易等21家中秋月饼盘点
  15. Failed to introspect Class [com.ssm.controller.OrderController] from ClassLoader [ParallelWebappClas
  16. 自我复盘-20210820
  17. 【程序源代码】微信小程序商城管理系统(java后台+小程序)
  18. linux查看摄像头参数+获取公网地址
  19. 中国品牌日话品牌:智能家居企业如何打造新消费品牌?
  20. 计算机基础知识判断题答案,计算机基础知识试题及答案判断题

热门文章

  1. 简单人物画像_10天学会画画 第5天:简单人物画法
  2. 超详细的Latex快速基础入门 (第二节)【关于latex命令的一些知识】
  3. 找到小菇凉 (BFS)
  4. linux 内核网络中 RPS/RFS 原理Ⅰ
  5. 视频渲染靠cpu还是显卡 视频渲染的作用是什么
  6. win7变成xp风格了怎么改回_win7怎么变成xp界面|win7系统变成xp界面主题的方法
  7. (附源码)springboot助农电商系统 毕业设计 081919
  8. html设置图像边框的属性,css3将图像设置为元素周围边框的方法
  9. 1's Complement和2's Complement的区别
  10. 阿里小蜜:语音识别、语义分析、深度学习在手机淘宝的实战分享