黑马程序员——java基础——递归

来源:互联网 发布:php中魔术常量 编辑:程序博客网 时间:2024/06/12 00:43

一, 什么是递归

递归是一种算法,在各种程序设计语言中被广泛利用,就是一个方法直接或者间接调用自身的方法,通俗来说就是方法自己调用自己。正是由于递归出现,它可以大将型复杂的问题层层转化成于原问题相似的小规模的问题以便于处理,可以实现只需要少量的代码就可以描述出解题过程中大量的重复计算。


二, 递归的优点

代码简洁,思路明了,结构清晰。比如:我们获取一个文件夹中的所有的文件,要是我们用循环来实现的话很困难,因为我们无从知道这个文件夹的目录层级道理有多深,无法去控制这个循环的次数,如果利用递归来解决这个问题就会变得很简单,而且最后实现该功能的代码量不多,阅读性很强。


三, 递归的缺点

递归需要系统 堆栈,对资源的消耗比较大并且效率不高,很容易导致内存溢出。所以可以不利用递归的地方尽量避免使用递归,尽可能用非递归的方式去实现我们的功能。


四, 递归注意的地方

A:一定要给递归一个出口。要是递归没有出口的话,那么就会一直进行压栈的动作没有有弹栈,就会在内存中不断的开辟空间但不会释放空间,这很容易就会导致内存溢出,造成系统崩溃。所以我们在用递归的时候千万要记得给定一个出口。

B:递归的次数不能太多。因为我们的内存的容量是有限的,要是递归的次数太多,所需要内存空间大于我们实际剩余的内存空间的话 也会导致内存溢出。

C:在构造函数中不能使用递归。


五, 递归应用举例

下面通过两个例子加深对递归的理解

A:IO流+递归实现copy文件夹


public static void main(String[] args) throws IOException {//指定一个要复制的文件夹 并封装成File对象File dir=new File("H:\\Evernote 导出文件");//明确目的地的路径File desPath=new File("g:\\");//调用copy文件夹的方法copyDirectory(dir, desPath);}//copy文件夹的方法public static void copyDirectory(File dir,File desPath) throws IOException{//先根据目的路径  获取到目的地路径下的文件夹的File对象File desDir=new File(desPath.getAbsolutePath()+"\\"+dir.getName());;//如果dir是文件夹就创建文件夹if(dir.isDirectory()){desDir.mkdir();}//获取dir目录下的所有内容 封装到File数组中File[] dirs=dir.listFiles();for(File f : dirs){//如果是文件夹就进行递归if(f.isDirectory()){copyDirectory(f,desDir);}//如果是文件的话就用IO流copy问价else{//定义字符读取流FileInputStream in=new FileInputStream(f);//定义字符输出流FileOutputStream out=new FileOutputStream(new File(desDir.getAbsoluteFile()+"\\"+f.getName()));//定义缓冲区byte[] buf=new byte[1024];int len=0;//从源文件中读取数据写入到目的文件中while((len=in.read(buf))!=-1){out.write(buf,0,len);out.flush();}//关闭流in.close();out.close();}}}}


B:利用递归实现一个十进制的数转换成其他机制。

说说该方法实现原理,比如要将6要装换成2进制的话,就是不断的除以2求把余数记录下来,直到得到的商的数值小于除数,这个过程可以用下面的这张图片来演示。


因为java中负数在计算中是按照其对应的正数取反加1来存储的所以这种方法不能实现求出负数的二进制。

public static String toBinary(int num){//定义一个字符串容器用来装最后的结果StringBuilder resultBuilder=new StringBuilder();//创建一个char数组 利用该数组完成查表操作  并为该数组赋初始值  因为是转换成二进制 最后的结果中只会出现0,1 所以findArr只用赋2个值char[] findArr=new char[]{'0','1'};//将结果以字符串形式返回return to(num,2,resultBuilder,findArr);}public static String toOctal(int num){//定义一个字符串容器用来装最后的结果StringBuilder resultBuilder=new StringBuilder();//创建一个char数组 利用该数组完成查表操作  并为该数组赋初始值  因为是转换成八进制 最后的结果中只会出现0-7 所以findArr只用赋8个值char[] findArr=new char[]{'0','1','2','3','4','5','6','7'};//将结果以字符串形式返回return to(num,8,resultBuilder,findArr);}public static String toHex(int num){//定义一个字符串容器用来装最后的结果StringBuilder resultBuilder=new StringBuilder();//创建一个char数组 利用该数组完成查表操作  并为该数组赋初始值  因为是转换成十六进制 最后的结果中只会出现0-f所以findArr只用赋16个值char[] findArr=new char[]{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};//将结果以字符串形式返回return to(num,16,resultBuilder,findArr);}//这个方法是用来帮助完成进制的转换的 就是toBinary() toHex() toOctal()三个方法将公共的代码进行了封装public static String  to(int num,int set,StringBuilder resultBuilder,char[] findArr){//如果传进来的数是0就直接返回“0”if(num==0){return "0";}//如果穿件来的数字是负数 就返回nullif(num<0){return null;}//如果大于0就进行递归if(num>0){to( num/set,set,resultBuilder,findArr);//将每次通过查表法得到的数据 存到resultBuilder中resultBuilder.append(findArr[num%set]);//将最后的结果转换成字符串返回return resultBuilder.toString();}return null;}



利用上面的to()方法写出转换成其他进制的方法 比如:写出十进制转换成4进制的方法

public static String toQuanternary(int num){ <span style="white-space:pre"></span>//定义一个字符串容器用来装最后的结果StringBuilder resultBuilder=new StringBuilder();//创建一个char数组 利用该数组完成查表操作  并为该数组赋初始值  因为是转换成四进制 最后的结果中只会出现0-3所以findArr只用赋4个值        char[] findArr=new char[]{'0','1','2','3'};        //返回结果        return to(num,4,resultBuilder,findArr);}






0 0
原创粉丝点击