八大算法思想(三)------------------递归算法

一,充分利用自己的递归算法思想

递归算法能够充分挖掘自身的潜力,无论遇到了什么问题,它都会直接或者间接地调用自身的算法去解决。

递归算法思想的原则是有事不求人。即使难以解决解决也要自己解决,即使难以解决也要硬着头皮去解决。递归的自身算法往往用函数的形式体现,所以递归算法需要预先编写功能函数,这些函数是独立的功能,能够实现解决某个问题的具体功能,当需要时直接调用这个函数即可。

1,递归算法的基础

在计算机编程应用中,递归算法对解决大多数问题是十分有效的,她能够使算法的描述变得简介而且易于理解,递归算法有如下3个特点:

(1)递归过程一般通过函数或子过程来实现。

(2)递归算法在函数或子过程的内部,直接或者简介地调用自己的算法。

(3)递归算法实际上是把问题转化为规模缩小了的同类问题的子问题,然后在递归调用函数或过程来表示问题的解。

2 ,在使用递归算法时,注意一下几点 (1)递归是在过程或 函数中调用自身的过程

(2)在使用递归策略时,必须有一个明确的递归结束条件,这称为递归出口。

(3)递归算法通常显得很简洁,但是运算效率较低,所以一般不提倡使用递归算法设计程序。

(4)在递归调用过程中,系统用栈来存储每一层的的返回点和局部变量。如果递归次数过多,则容易造成栈溢出,所以一般不提倡用递归算法设计程序。

3,实例----------汉诺塔问题:

一个庙里有三个柱子,第一个有64个盘子,从上往下盘子越来越大。要求庙里的老和尚把这64个盘子全部移动到第三个柱子上。移动的时候始终只能小盘子压着大盘子。而且每次只能移动一个。

1、此时老和尚(称为第1个和尚)他想:要是有一个人能把前63个盘子先移动到第二个柱子上,我再把最后一个盘子直接移动到第三个柱子,再让那个人把刚才的前63个盘子从第二个柱子上移动到第三个柱子上,我的任务就完成了,简单。所以他找了第2个和尚,让其:

    ① 你把前63个盘子移动到第二柱子上

    ② 在我自己把第64个盘子一道第三个柱子上后

    ③ 你把前63个盘子移动到第三柱子上

2、第2个和尚接了任务后和第1个和尚一样想:要是有一个人能把前62个盘子先移动到第三个柱子上,我再把最后一个盘子直接移动到第二个柱子,再让那个人把刚才的前62个盘子从第三个柱子上移动到第三个柱子上,我的任务就完成了,所以他也找了比他年轻的和尚叫他第3和尚,让其:

    ① 你把前62个盘子移动到第三柱子上

    ② 在我自己把第63个盘子一道第二个柱子上后

    ③ 你把前62个盘子移动到第二柱子上

3、第3个和尚接了任务,又把移动前61个盘子的任务依葫芦话瓢的交给了第4个和尚,等等递推下去,直到把任务交给了第64个和尚为止(估计第64个和尚很郁闷,没机会也命令下别人,因为到他这里盘子已经只有一个了)。

4、到此任务下交完成,到各司其职完成的时候了。完成回推了:

第64个和尚移动第1个盘子,把它移开,然后第63个和尚移动他给自己分配的第2个盘子。第64个和尚再把第1个盘子移动到第2个盘子上。到这里第64个和尚的任务完成,第63个和尚完成了第62个和尚交给他的任务的第一步。

从上面可以看出,只有第64个和尚的任务完成了,第63个和尚的任务才能完成,只有第2个和尚任务完成后,第1个和尚的任务才能完成。这是一个典型的递归问题。

递归(recursion):程序调用自身的编程技巧。
递归满足2个条件:

1)有反复执行的过程(调用自身)

2)有跳出反复执行过程的条件(递归出口)

递归与栈的关系

下面演示的是求n的阶乘

intFactorial(int n){ 

if(n == 0)return1; returnn * Factorial(n - 1);

}

常常听到 “递归的过程就是出入栈的过程”,这句话怎么理解?我们以上述代码为例,取 n=3,则过程如下:

第 1~4 步,都是入栈过程,Factorial(3)调用了Factorial(2),Factorial(2)又接着调用Factorial(1),直到Factorial(0);

第 5 步,因 0 是递归结束条件,故不再入栈,此时栈高度为 4,即为我们平时所说的递归深度;

第 6~9 步,Factorial(0)做完,出栈,而Factorial(0)做完意味着Factorial(1)也做完,同样进行出栈,重复下去,直到所有的都出栈完毕,递归结束。

每一个递归程序都可以把它改写为非递归版本。我们只需利用栈,通过入栈和出栈两个操作就可以模拟递归的过程,二叉树的遍历无疑是这方面的代表。

但是并不是每个递归程序都是那么容易被改写为非递归的。某些递归程序比较复杂,其入栈和出栈非常繁琐,给编码带来了很大难度,而且易读性极差,所以条件允许的情况下,推荐使用递归。

示例题目

1.有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少对?请使用递归和非递归实现。

import java.util.Scanner;publicclass Main{/** 兔子的规律为数列1,1,2,3,5,8,13,21.... 这是一个菲波拉契数列问题 {斐波拉契数列原理:除开前两项 后面每位数等于前两项相加之和}

* 1.通过中间值来保存上一月兔子的和 2.在将上一月兔子这一月兔子相加 得到下一月数量和*/// 非递归publicstaticvoidf1(int month) {intrabbit = 1;// 上月兔子的数量和intnewRabbit = 1;// 这一月生成兔子的数量和intcount;// 中间值 用来存数量的if(month == 1) {

System.out.println("第1月兔子 1 对");

} elseif(month == 2) {

System.out.println("第2月兔子 1 对");

} else {// 从第三月起for(inti = 3; i <= month; i++) {

count = newRabbit;

newRabbit = rabbit + newRabbit;

rabbit = count;

}

System.out.println("第" + month + "月兔子 " + newRabbit + " 对");

}

}// 递归publicstaticintf2(int month) {if(month == 1 || month == 2) {return1;

}// 上一个月的兔子数intrabbit1 = f2(month - 1);// 上一个月的前一个月兔子数intrabbit2 = f2(month - 2);returnrabbit1 + rabbit2;

}publicstaticvoid main(String[] args) {

Scanner sc =new Scanner(System.in);intmonth = sc.nextInt();

f1(month);

System.out.println("============");

System.out.println("第" + month + "月兔子 " + f2(month) + " 对");

}

}

2.十进制转二进制

import java.util.Scanner;/*

* 十进制转二进制*/publicclass Main {// 非递归publicstaticvoidf1(int n) {intt = 0;intbin = 0;intr = 0;while(n != 0) {

r = n % 2;

n = n / 2;

bin += r * Math.pow(10, t);

t++;

}

System.out.println(bin);

}// 递归publicstaticvoidf2(int n) {if(n / 2 == 0) {

System.out.print(n % 2);

} else {

f2(n / 2);

System.out.print(n % 2);

}

}publicstaticvoid main(String[] args) {

System.out.println("请输入一个非负的十进制整数:");

Scanner sc =new Scanner(System.in);intnumber = sc.nextInt();if(number < 0) {

System.out.println("不符合要求");

} else {

System.out.print("对应的二进制:");

f1(number);

System.out.println("=================");

System.out.print("对应的二进制:");

f2(number);

}

}

}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 计算机科学的新学生通常难以理解递归程序设计的概念。递归思想之所以困难,原因在于它非常像是循环推理(circular...
    启明_b56f阅读 12,168评论 0 20
  • 每章一点正能量:人的一生可能燃烧也可能腐朽。 前言 相信大家在面试或者工作中偶尔会遇到递归算法的提问或者编程,我们...
    Coder编程阅读 5,310评论 0 2
  • 之前分享了一篇随机算法,这次再把以前写的递归算法的文章梳理一下,这篇文章主要是受到宋劲松老师写的《Linux C编...
    __七把刀__阅读 14,068评论 3 27
  • 记得小时候经常讲的一个故事:从前有座山,山上有座庙,庙里有一个老和尚和一个小和尚,一天,老和尚给小和尚讲了一个故事...
    IT可乐阅读 3,349评论 0 3
  • 前言 递归是算法中一种非常重要的思想,应用也很广,小到阶乘,再在工作中用到的比如统计文件夹大小,大到 Google...
    谢kun阅读 12,709评论 0 15

友情链接更多精彩内容