版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Albert_Bolt/article/details/82356551
递归
定义
- 若一个对象部分地包含它自己, 或用它自己给自己定义, 则称这个对象是递归的;若一个过程直接地或间接地调用自己, 则称这个过程是递归的过程。
三种递归情况
- 定义是递归的
- 阶乘函数:n=0,n! = 1;n>=1,n! = n*(n-1)!
- 斐波那契数列:n<=1,fib(n) = n;n>1,fib(n) = fib(n-1) + fib(n-1)
- 数据结构是递归的
- 单链表:递归找某一值为x的节点,若节点值为x,则返回节点数值;若节点值不为x,则递归找节点。
- 问题的解法是递归的
- 汉诺塔问题:有ABC三根柱子,A上有一些盘子,按从小到大顺序放置,把A上的盘子移到C上,并且要保证盘子也是按照从小到大顺序放置。求这个移动的过程。如果 n = 1,则将这一个盘子直接从 A 柱移到 C 柱上。否则,执行以下三步:
① 用 C 柱做过渡,将 A 柱上的 (n-1) 个盘子移到 B 柱上:
② 将 A 柱上最后一个盘子直接移到 C 柱上;
③ 用 A 柱做过渡,将 B 柱上的 (n-1) 个盘子移到 C 柱上。
- 汉诺塔问题:有ABC三根柱子,A上有一些盘子,按从小到大顺序放置,把A上的盘子移到C上,并且要保证盘子也是按照从小到大顺序放置。求这个移动的过程。如果 n = 1,则将这一个盘子直接从 A 柱移到 C 柱上。否则,执行以下三步:
递归过程改为非递归过程
- 递归过程效率低,重复计算多,改为非递归过程的目的是提高效率
- 单向递归和尾递归可直接用迭代实现其非递归过程
- 其他情形必须借助栈实现非递归过程
应用1:n皇后问题
- 在 n 行 n 列的国际象棋棋盘上,若两个皇后位于同一行、同一列、同一对角线上,则称为它们为互相攻击。n皇后问题是指找到这 n 个皇后的互不攻击的布局。
- 解决:
- 在第 i 行放皇后时,需要在列的方向从 0 到 n-1 试探 ( j = 0, …, n-1 )
- 在第 j 列放一个皇后,如果在列、主对角线、次对角线方向有其它皇后,则出现攻击,撤消在第 j 列安放的皇后。如果没有出现攻击,在第 j 列安放的皇后不动,递归安放第 i+1行皇后。
应用2:骑士问题
- 骑士问题是在一个N*N的棋盘上,给骑士一个起始坐标,骑士必须从起点开始行走,把棋盘上的每一点都走过。骑士的走法就是国际象棋中的骑士走法。
- 解决:
- 将八个可能的移动方向使用数组来存放
- 在移动之前必须另外判断下一步有没有走出了边界
- 当骑士走到某一位置时,下一个移动的位置是八个位置中的其中一个,从0这个方向开始走,如果新位置未走过的话,就可以移到新位置上,并记录下所走的步数,如果新位置已被走过,则继续找下一个方向。
- 递归的终止条件为:骑士所走的步数等于N*N
(由于是N * N的棋盘,所以骑士必须走N2-1步,才能将棋盘上的每一点都走过,即棋盘的大小排除一开始的起始位置那一点。因此若设起点为第一步,则全部走完时最后一步的步数会刚好是棋盘的大小N * N,所以,骑士所走的步数等于N * N,则代表骑士已经全部走完。)
应用3:十进制转换为八进制:
- 令递归函数为fun,要转换的数为num
- 如果 num<=8,返回 num
- 然后递归求 num / 8 的返回值,用这个值 乘以 10 加上 num 模 8 就是最后的结果
if(num<=8) return num;
return num % 8 + 10 * func(num/8);