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!所有零的个数,用递归

/**
 * 需求:求出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
 * */		
package com.yy.test;

public class Test7 {
																																											
	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);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

beyond谚语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值