Java——递归练习

练习一:从键盘接收一个文件夹路径,统计该文件夹大小

分析:

每句话相当与每一个要求,每一个要求用一个方法去实现

第一个方法
 * getDir()
 * 第一个要求:从键盘接收一个文件夹路径
 * 1,创建键盘录入对象
 * 2,定义一个无限循环
 * 3,将键盘录入的结果存储并封装成File对象
 * 4,对File对象判断
 * 5,将文件夹路径对象返回
第二个方法
 * getFileLength(File dir),传入第一个方法所输入并且经过判断筛选之后的文件夹路径File dir
 * 第二个要求:统计该文件夹大小
 * 1,定义一个求和变量
 * 2,获取该文件夹下所有的文件和文件夹  ListFiles();
 * 3,遍历数组
 * 4,判断如果是文件,就计算大小并累加
 * 5,判断如果是文件夹,就递归调用    只有是文件夹才进行递归调用,是因为,文件夹大小不能直接获取,而文件可以直接获取字节个数

具体代码如下:

package com.yy.test;

import java.io.File;
import java.util.Scanner;

public class Test1 {
    /**
     * 需求:
     * 1,从键盘接收一个文件夹路径,统计该文件夹大小
     * 
     * 第一个方法
     * getDir()
     * 第一个要求:从键盘接收一个文件夹路径
     * 1,创建键盘录入对象
     * 2,定义一个无限循环
     * 3,将键盘录入的结果存储并封装成File对象
     * 4,对File对象判断
     * 5,将文件夹路径对象返回
     * 
     * 第二个方法
     * getFileLength(File dir),传入第一个方法所输入并且经过判断筛选之后的文件夹路径File dir
     * 第二个要求:统计该文件夹大小
     * 1,定义一个求和变量
     * 2,获取该文件夹下所有的文件和文件夹  ListFiles();
     * 3,遍历数组
     * 4,判断如果是文件,就计算大小并累加
     * 5,判断如果是文件夹,就递归调用    只有是文件夹才进行递归调用,是因为,文件夹大小不能直接获取,而文件可以直接获取字节个数
     * 
     * */
    public static void main(String[] args) {


        File  dir = getDir();                           //调用第一个方法,直接获取文件夹
        System.out.println(getFileLength(dir));

        /*
        File dir = new File("F:\\wps");                 //返回结果为0,也就是不能直接获取文件夹大小
        System.out.println(dir.length());               //直接获取文件夹的结果为0
        */


        }
    /**
     * 从键盘接收一个文件夹路径
     * 方法分析:
     * 1,返回值类型为File   获取文件夹路径,所以返回值类型是File
     * 2,参数列表无
     * */
    public static File getDir(){
        Scanner wsq = new Scanner(System.in);                               //创建键盘录入对象
        System.out.println("请输入一个文件路径:");                               //输出一个提示语句
        while(true){                                                        //定义一个无限循环
            String line = wsq.nextLine();                                   //将键盘录入的结果存储到line里;String nextLine():此扫描器执行当前行,并返回跳过的输入信息。 此方法返回当前行的其余部分,不包括结尾处的行分隔符。当前位置移至下一行的行首。
            File dir = new File(line);                                      //并将line封装成File对象dir
            if(!dir.exists()){                                              //对File对象dir,进行判断,如果录入的文件夹路径不存在 ;boolean exists():当且仅当此抽象路径名表示的文件或目录存在时,返回 true;否则返回 false 
                System.out.println("您录入的文件夹路径不存在,请输入一个文件夹路径: ");    //给予提示
            }else if(dir.isFile()){                                         //对File对象dir,进行判断,如果录入的是文件路径;boolean isFile():当且仅当此抽象路径名表示的文件存在且 是一个标准文件时,返回 true;否则返回 false 
                System.out.println("您录入的是文件路径,请输入一个文件夹路径: ");       //给予提示
            }else {                                                         //对File对象dir,进行判断,录入的是文件夹路径
                return dir;                                                 //将文件夹路径对象返回
            }
        }
    }
    /**
     * 统计该文件夹大小
     * 方法分析:
     * 1,返回值类型long    length()方法的返回值是long
     * 2,参数列表File dir
     * */
    public static long getFileLength(File dir){
        long len = 0;                                                       //定义一个求和变量
        File [] subFiles = dir.listFiles();                                 //获取该文件夹下所有的文件和文件夹 ;File[] listFiles():返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
        for (File subFile : subFiles) {                                     //遍历数组;使用增强for循环遍历 
            if(subFile.isFile()){                                           //判断如果是文件
                len = len + subFile.length();                               //就计算大小并累加到求和变量len上
            }else{                                                          //判断如果是文件夹
                len = len + getFileLength(subFile);                         //就再次调用该方法,进行递归调用;不能直接获取文件夹大小,文件可以直接获取字节个数
            }
        }
        return len;                                                         //最后,返回求和变量len的值
    }
}

练习二:从键盘接收一个文件夹路径,删除该文件夹;(删除要慎重,因为删除的内容不经过回收站)

分析:

 *1,获取该文件夹下的所有的文件和文件夹
 *2,遍历数组
 *3,判断是文件直接删除
 *4,如果是文件夹,递归调用
 *5,循环结束后,把空文件夹删掉

package com.yy.test;

import java.io.File;

public class Test2 {
    public static void main(String[] args) {
        File dir = Test1.getDir();              //对方法进行调用,调用Test1里面的getDir()方法,即从键盘接收一个文件夹路径的方法,获取文件夹路径
        deleteFile(dir);
    }

    /**、
     * 删除文件夹
     * 方法分析
     * 1,返回值类型void   因为删除嘛,不需要任何的返回,直接删掉就可以了
     * 2,参数列表File dir
     * */
    public static void deleteFile(File dir){
        File [] subFiles = dir.listFiles();     //获取该文件夹下的所有的文件和文件夹   listFiles():返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
        for (File subFile : subFiles) {         //遍历数组
            if(subFile.isFile()){               //判断是文件
                subFile.delete();               //直接删除
            }else{                              //判断是文件夹
                deleteFile(subFile);            //递归调用
            }
        }
        dir.delete();                           //循环结束后,把空文件夹删掉;若不加这个,只会把文件给删掉,而不会把文件夹给删掉,会留有空文件夹
    }

}

练习三:从键盘接收两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中

例如,第一次录入的文件夹路径是 F:\wsq ,第二个录入的文件夹路径是 F:\yy

运行结束之后,就是在 F:\yy 该路径下重新将 wsq 文件夹全部拷贝下来;

F:\yy\wsq,其中yy是父级路径,wsq是子级路径

分析:

  • 1,在目标文件夹中创建原文件夹 原文件夹 原文件夹
  • 2,获取原文件夹中所有的文件和文件夹,存储在File数组中
  • 3,遍历数组
  • 4,如果是文件就用IO流读写 IO流只能读写文件不能读取文件夹
  • 5,如果是文件夹,就递归调用
package com.yy.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test3 {
/**
 * @throws IOException 
 * */
    public static void main(String[] args) throws IOException {
        File wsq = Test1.getDir();
        File yy =  Test1.getDir();
        if(wsq.equals(yy)){
            System.out.println("目标文件夹是原文件夹的子文件夹");
        }else{
            copy(wsq,yy);
        }
    }
/**
 * 把其中一个文件夹中(包含内容)拷贝到另一个文件夹中
 * 1,返回值类型void
 * 2,参数类型File wsq(原),File yy()
 * @throws IOException 
 * 
 * */
private static void copy(File wsq, File yy) throws IOException {
    File newDir = new File(yy,wsq.getName());                       //在目标文件夹中创建原文件夹
    // getName():返回由此抽象路径名表示的文件或目录的名称
    // mkdirs():创建此抽象路径名指定的目录,包括所有必需但不存在的父目录;当且仅当已创建目录以及所有必需的父目录时,返回 true;否则返回 false 
    newDir.mkdir();                                                 //这一步骤完成之后,就相当于在yy文件夹下创建wsq文件
    File [] subFiles = wsq.listFiles();                             //获取原文件夹(wsq)下的所有的文件和文件夹,存储在File数组中
    for (File subFile : subFiles) {                                 //遍历数组;
        if(subFile.isFile()){                                       //如果是  文件  ,就用IO流(字节流)读写
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(subFile));    //输入流;字符流只能拷贝文本,拷贝文件可以是任意的文件,不止是拷贝文本,所以说,只能用字节流,不能用字符流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(newDir,subFile.getName())));      //输出流;getName():返回由此抽象路径名表示的文件或目录的名称

            int b;
            while((b = bis.read()) != -1){
                bos.write(b);
            }
            bis.close();                                            //关流
            bos.close();                                            //关流
        }else{                                                      //如果是  文件夹  ,就递归调用
            copy(subFile,newDir);
        }
    }

}

}

练习四:从键盘接收一个文件夹路径,把文件夹中的所有文件以及文件夹的名字按层级打印

分析:

  • 1,获取所有文件和文件夹,返回的File数组
  • 2,遍历数组
  • 3.无论是文件还是文件夹,都需要直接打印
  • 4,如果是文件夹,递归调用
package com.yy.test;

import java.io.File;

public class Test4 {
    public static void main(String[] args) {
        File dir = Test1.getDir();                  //获取文件夹路径   
        printLev(dir,0);
    }

    public static void printLev(File dir,int lev) {
        //1,把文件夹中的所有文件以及文件夹的名称按层级打印
        File [] subFiles = dir.listFiles();     
        //2,遍历数组
        for (File subFile : subFiles) {
            for(int i = 0 ;i<=lev ; i++){
                System.out.println("\t");
            }
        //3.无论是文件还是文件夹,都需要直接打印
            System.out.println(subFile);
        //4,如果是文件夹,递归调用
            if(subFile.isDirectory()){
                printLev(subFile,lev + 1);
            }
        }

    }
}

练习五:斐波那契数列(数组求跟递归求两种方法)

package com.yy.test;

public class Test5 {
    /**
     * 不死神兔
     * 故事得从西元1202年说起,话说有一位意大利青年,名叫斐波那契。
     * 在他的一部著作中提出了一个有趣的问题:假设一对刚出生的小兔,一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生下一对小兔
     * 问:一对刚出生的兔子,一年内繁殖成多少对兔子?
     * 1  1  2  3  5  8  13  21  34 ...... 
     * 
     * 
     * */
    public static void main(String[] args) {
//      demo1();                                    //用数列求,不用递推
        System.out.println(fun(22));                //调用递归方法求

    }

    private static void demo1() {
        //用数组做不死神兔
        int [] arr = new int [10];
        //数组中第一个元素和第二个元素都为1
        arr[0] = 1;
        arr[1] = 1;
        //遍历数组对其他元素赋值
        for (int i = 2; i < arr.length; i++) {
            arr [i] = arr[i-2] + arr[i-1];
        }
        /*
         //可以提供循环,全部打印出来
        for (int i = 0; i < arr.length; i++) {
            System.err.println(arr[i]);
        }
        */

        System.out.println(arr.length-1);               //也可以只打印最后一个月,兔子的对数
    }

    /**
     * 用递归来求斐波那契数列
     * */
    public static int fun(int num){
        if(num == 1 || num == 2){
            return 1;
        }else {
            return fun(num - 1) + fun(num - 2);
        }
    }
}

练习六:斐波那契数列(数组求跟递归求两种方法)

①求出1000!所有零的个数,不用递归

package com.yy.test;

import java.math.BigInteger;

public class Test6 {
/**
 * 需求:求出1000!所有零的个数,不用递归
 * 
 * 
 * */
    public static void main(String[] args) {
    /*
        int result = 1;
        for (int i = 0; i <= 1000; i++) {
            result = result * i;
        }
        System.out.println(result);                 //最后的输出结果为0,因为1000!远大于int的取值范围,所以输出最后的结果为0
    */

        demo1();
        demo2();



    }

private static void demo2() {                   //获取1000!尾部有多少个零
    BigInteger bi1 = new BigInteger("1");
    for (int i = 1; i <= 1000; i++) {
        BigInteger bi2 = new BigInteger(i + "");
        bi1 = bi1.multiply(bi2);                //将bi1与bi2相乘的结果赋值给bi1
    }
    String str = bi1.toString();                //获取字符串表现形式
    StringBuilder sb = new StringBuilder(str);
    str = sb.reverse().toString();              //链式编程

    int count = 0;                              //定义计数器
    for (int i = 0; i < str.length(); i++) {
        if('0' != str.charAt(i)){
            break;
        }else{
            count ++;
        }
    }

    System.out.println(count);
}

private static void demo1() {                   //求1000!中所有的零
    BigInteger bi1 = new BigInteger("1");
    for (int i = 1; i <= 1000; i++) {
        BigInteger bi2 = new BigInteger(i + "");
        bi1 = bi1.multiply(bi2);                //将bi1与bi2相乘的结果赋值给bi1
    }
    System.out.println(bi1);
    String str = bi1.toString();                //获取字符串表现形式
    int count = 0;
    for(int i = 0; i <str.length(); i ++){
        if('0' == str.charAt(i)){
            count ++;
        }
    }
    System.out.println(count);
}



}

②求出1000!所有零的个数,用递归

package com.yy.test;

public class Test7 {
/**
 * 需求:求出1000!尾部零的个数,用递归做
 * 5  10  15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90  95  100  ...  1000                                                1000/5=200
 * 5 * 5   5 * 5 * 2   5 * 5 * 3   5 * 5 * 4   5 * 5 * 5   5 * 5 * 6                                                                        200/5=40
 * 5 * 5 * 5 * 1    5 * 5 * 5 * 2     5 * 5 * 5 * 3    5 * 5 * 5 * 4    5 * 5 * 5 * 5    5 * 5 * 5 * 6   5 * 5 * 5 * 7   5 * 5 * 5 * 8      40/5=8
 * 5 * 5 * 5 * 5 * 5                                                                                                                        8/5=1 
 *                                                                                                                                          200+40+8+1=249
 * */                                                                                                                                                                                   
    public static void main(String[] args) {

        System.out.println(fun(1000));
    }
    public static int fun(int num){
        if(num > 0 && num < 5){
            return 0;
        }else {
            return num / 5 + fun(num / 5);
        }

    }
}

练习七:约瑟夫环

故事:从前有个叫约瑟夫环的国王,国王有一天很高兴,就把监狱里面的500个死囚犯带出来,说:“你们开始排队,从1开始以此报数,若是3的倍数就直接拉出去给杀掉,最后剩余1个人,无罪释放。”

问题:键盘输入人数,然后进排序,从1开始以此报数,若是3的倍数的人会被杀掉,后面的人接着报数。

例如:10个人

1 2 3 4 5 6 7 8 9 10
11 12 被杀 13 14 被杀 15 16 被杀 17
18 被杀 19 20 被杀 21 22
被杀 23 24 被杀 25
26 被杀 27
28 被杀
最后只有一个人生还,就是 4。

package com.yy.test;

import java.util.ArrayList;

public class Test8 {
    public static void main(String[] args) {
        System.out.println(getLuckluNum(8));
    }
/**
 * 获取幸运数字
 * 1,返回值类型int
 * 2,参数列表int num
 * 
 * */
    public static int getLuckluNum(int num){
        ArrayList<Integer> list = new ArrayList<>();    //创建集合存储1到num对象
        for (int i = 1; i <= num; i++) {                //将1到num存储在集合中 
            list.add(i);                        
        }
        int count = 1;                                  //用来数数的,只要是3的倍数就杀人
        for (int i = 0;  list.size() != 1; i++) {   //只要集合中人数超过1,就要不断地杀
            if(i == list.size()){                       //如果i增长到集合最大的索引+1时
                i = 0;                                  //重新归零
            }

            if(count % 3 == 0){                         //如果是3的倍数就杀人
                list.remove(i--);
            }

            count++;
        }
        return list.get(0);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41264055/article/details/81227317