package cn.dg;
/**
* 哈喽,大家好!
* 今天讲一下Java中的递归;
*
* 递归
* 所谓的递归:就是是自己调用自己;
* 当然我们不能让自己的程序一直这样重复下去,因此递归使用时一定要注意它的规则边界;
*
* 递归分类:
* 接下来聊一下递归常见的表现形式;
* 一般我们对于递归的应用无非就两种情况:
* 1. 自己调用自己;(直接递归)
* 2. A,B,N+ 回调 A,B,N+;(间接递归)
* 我们称第一种自己调用自己的这种递归方式为常用的直接递归;
* 而第二种大型递归方式称为间接递归;
*
* 规则边界:
* 1. 构造方法不能递归;(构造器是用来创建对象的,因而不能让这种消耗型动作持续的去创建对象)
* 2. 递归运算在设计过程中一定要有作为出口的终止限定条件;(死循环会造成栈内存溢出)
* 3. 同样,设计递归运算时一定要考虑到递归实际占用内存的问题,要对递归的次数添加限定;
* (如果还没有执行到跳出递归的条件约束,JVM内存就用光,也会报栈内存溢出;)
*
* 好,还是和以前一样;
* 首先创建一个自己的测试类;
* @author TANJIYUAN
*/
public class DgTest {
/**
* 创建一个计算1~n位数字之和的方法;
* 实现:
* 1+2+3+n...
* x+(x+1)|x+(++x); -> 1+(1+1) -> 1+2
* x+(x+1)|x+(++x); -> 2+(2+1) -> 2+3
* x+(x+1)|x+(++x); -> ...
* 在程序中实现可以把第二步2+3的缺值通过补足的方式来弥补;ok;
* 那清晰了思路,实现起来就相对easy;Let's go...
*
*
* 在goon(int num)这个方法中:
* 所实现的方法是限制基数重大大小递减的方式(当然也可以使用由小到大的方式);实现;
*
* @param num
* @return
*/
public static int goon(Integer num) {
/**
* 首先判断一种特殊情况:
* 我们的方法设计开始的规则是:计算1以上的相加数之和;
* 那么也就说如果是1本身,那无需计算;
* 那么在这里直接做返回处理即可;
*/
if(num == 1) {
return 1;
}
/**
* 如果用户输入的数字是负数或者0;计算没有多大意义;
* 所以直接将这种情况作为出口项进行设计;
*/
if(num <= 0) {
return 0;
}
/**
* 如果用户传入的参数过大,超出运行内存的大小;
* 在这里是需要作为出口项控制一下的;
*/
if(num >= 500) {
return 0;
}
/**
* 这个地方呢要详细的说一下:
* 如非大牛之辈恐难以直观;
* 我们通过一开始的设计分析发现;其实每次的数据计算都有一个公式x+(++x);
* 那么这个公式所缺的无非就是上一次计算的数据;
*
* 这一点我们可以直接通过回调赋值的方式来弥补;(这是我个人对递归方式调用的称谓)
*
* 那么num-1是什么呢?
* 此处想了n久,从小打到的设计思路实现代码会略微繁琐,故而采用了这种方式;
* 在方法调用的初期,调用者会预传一个int类型的参数进来,我需要做的无非就是
* 判断1以外的情况;以及对数据进行计算即可;
* 因此既然是相加之数,从小到大相加也是一个值;从大到小相加也是一个值,(恰巧用户输入的就是
* 一个大值)因此,果断采用的从大到小的方式,每次直接用传进来的参数计算即可,都不用处理;
* 到这里,相信各位已经有所了解这里面的运行机制;
*
*
* 最后呢说一下关于这次递归的两个关键性要素在哪里;
* 我们知道:递归的设计使用时一定要有规则边界的,否则必然会陷入死循环中;
* 因此我们这次的设计实现也不例外,那么下面就来说明一下这其中的规则边界;
*
* 首先递归的设计一定要有出口,那么我们的一开始的时候处理1和<=0以及>=500这种情况时,就是出口设计;
* 其中的>=500则是根据占用情况而设计的出口项;
*/
return num + goon(num-1);
}
/**
* 程序的入口|主函数;
* @param args
*/
public static void main(String[] args) {
/**
* 然后在这里调用;传入一个int类型的参数5来进行计算;
* 最终得出15的结果;
* 为了验证这个结果的正确性,我拿来了公司唯一的一台认不出牌子的计算器来进行验证;
* 最终得出...它是正确答案;
* 那么至此,关于Java中递归的一些小细节就算是告一段落了;
*
* 这个例子很多的地方都有引用到,我其实有想用其他的案例来带过;
* 但是小脑瓜还没开窍,一时间呢也没有更加舒心的案例来给大家说明;
* 所以就将就一下以此为例,来进行我们Java递归的案例说明;
*/
System.out.println(goon(5));
}
}
package cn.dg;
/**
* 对了,在这里再给大家给一个关于阶乘计算的Demo;
* 在开始之前大家先了解一下关于阶乘的内容;
* 首先什么是阶乘?
* 1. 阶乘是基斯顿·卡曼(Christian Kramp,1760~1826)于 1808 年发明的运算符号,是数学术语;
* 2. 一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1;
* 3. 自然数n的阶乘写作n!;
* 4. 写作:n!=1×2×3×...×(n-1)×n;
* 5. 那么用递归实现:0!=1,n!=(n-1)!×n;(其中0!=1就表示0的阶乘为1;)
*
* 好了,清晰了阶乘的原理,那下面就给大家列出关于阶乘利用递归方式实现的Demo;
*
* 首先还是和以前一样,我们先创建一个自己的测试类;
* @author Administrator
*
*/
public class DgTest {
/**
* 将阶乘处理的代码封装入一个方法中;
* 进行迭代机制的处理;
* @param num
* @return
*/
public static int goon(Integer num) {
/**
* 那么还是和之前一样;要进行出口项的设置;
* 如果参数<0的话没有计算的必要;因此将其设置为一项出口项处理;
*/
if(num < 0) {
return 0;
}
/**
* 在设计的时候很容易忘记这块的设计;
* 我们只顾着递减了,没有添加对应的限制,如果成0之后任何数相乘都等于0;
* 因此也要将此项当作一个出口项处理;
*/
if(num == 1) {
return 1;
}
/*
* 好,那到了最后就是我们的计算工作;
* 直接利用我们之前分析好的公式将其带入即可;
*/
return num * goon(num-1);
}
/**
* 程序入口|主函数;
* @param args
*/
public static void main(String[] args) {
/**
* 在这里进行封装好迭代方法的调用;
* 我们还是传入一个5的参数;
* 还是和之前一样,我准备了一个陈旧但精准的计算器,进行了结果验证;
* 最终的结论:它是对的;
*/
System.out.println(goon(5));
}
}
package cn.dg;
import java.io.File;
/**
* 下面再列一个文件获取的迭代Demo;
*
* 创建一个自己的测试类;
* @author Administrator
*
*/
public class DgTest {
/**
* 封装对应的迭代机制;
* @param file: 方法需要传入一个文件对象;
*/
public static void goonFile(File file) {
/**
* 通过文件对象获取该对象目录下的所有File目录对象;
* 以数组形式返回;
*/
File [] listFile = file.listFiles();
/**
* 循环数组;
*/
for(File thisFile : listFile) {
/**
* 出口项;
*
* isFile();
* 判断是否为文件;
*/
if(thisFile.isFile()){
/**
* getName();
* 打印文件的文件名;
*
* getAbsolutePath();
* 返回文件的绝对路径;
*/
System.out.println(thisFile.getName() + ": " + thisFile.getAbsolutePath());
}
/**
* isDirectory();
* 判断是否为文件夹;
*/
if(thisFile.isDirectory()) {
goonFile(thisFile);
}
}
}
/**
* 程序入口|主函数;
* @param args
*/
public static void main(String[] args) {
/**
* 初始化一个地址参数;
*/
String path = "D:\\Software\\JDK";
/**
* 实例化文件对象;
* 传入初始化的地址参数;
*/
File file = new File (path);
/**
* 调用封装好的方法;
*/
goonFile(file);
}
}