재귀
1. 개념 : 직접 호출
사례 : 요구 사항 : 개수 5!
방법 1 : for 루프 사용
int result=1;
for (int i = 1; i <=5; i++) {
result=result*i;
}
System.out.println(result);
}
방법 2 : 재귀 사용
public static int fun(int num) {
if (num ==1) {
return 1;
}else {
return num*fun(num-1);
}
}
단점: 재귀를 너무 많이 호출 할 수 없습니다. 그렇지 않으면 스택 메모리가 오버플로됩니다.
이익: 사이클 수를 알 필요가 없음
문제:
생성자는 재귀 호출을 사용할 수 없습니다. 재귀 호출에는 반환 값이 있거나 반환 값이 없을 수 있습니다.
재귀 운동 (1)
요구 사항 : 키보드에서 입력 할 폴더 경로 및 폴더의 모든 된 .java 파일 이름을 인쇄 할 수 있습니다.
분석 :
1. 폴더 경로 아래의 모든 파일과 폴더를 가져 와서 파일 배열
2 에 저장합니다 . 배열을 탐색하고 각 파일 또는 폴더를 판단합니다.
삼. 파일이고 접미사가 .java 인 경우 인쇄
4. 폴더 인 경우 재귀 적으로 호출
public class Demo1_Test {
public static void main(String[] args) {
File dir =getDir();
printJavaFile(dir);
}
public static File getDir() {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入一个文件夹路径:");
while (true) {
String line =scanner.nextLine();
File dir =new File(line);
if (!dir.exists()) {
System.out.println("您录入的文件夹路径不存在,请重新录入");
}else if (dir.isFile()) {
System.out.println("您录入的是文件夹路径,请重新录入文件路径");
}else {
return dir;
}
}
}
//获取文件夹路径下的所有.java文件
//返回值类型void
//参数列表File dir
public static void printJavaFile(File dir) {
//获取到该文件路径下的所有的文件和文件夹,存储在File数组中
File[] subFiles =dir.listFiles();
//遍历数组,对每一个文件或文件夹做判断
for (File subFile :subFiles) {
//如果是文件,并且后缀名是.java的就打印
if (subFile.isFile()&&subFile.getName().endsWith(".java")) {
System.out.println(subFile);
//如果是文件夹,就递归调用
}else if (subFile.isDirectory()) {
printJavaFile(subFile);
}
}
}
}
효과는 다음과 같습니다.
재귀 운동 (2)
요구 사항 : 키보드에서 폴더 경로 수신 및 폴더 크기 계산
분석 :
키보드에서 폴더 경로 수신
- 키보드 입력 개체 만들기
- 무선 루프 정의
- 키보드 입력 결과를 File 객체에 저장하고 캡슐화합니다.
- File 객체 판단
- 폴더 경로 객체 반환
폴더 크기 계산
- 합계 변수 정의
- 폴더에있는 모든 파일과 폴더를 가져옵니다. ListFiles ();
- 배열 탐색
- 파일이면 크기를 계산하고 합산
- 폴더인지 판단하고 재귀 적으로 호출
public class Demo2_Test {
public static void main(String[] args) {
//File dir =new File("d:\\day15");
//System.out.println(dir.length());//直接获取文件夹的结果是0
File dir =getFile();
System.out.println(getFileLength(dir));
}
public static File getFile() {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入一个文件夹路径");
while (true) {
String line =scanner.nextLine();
File dir = new File(line);
//对File对象进行判断
if (!dir.exists()) {
System.out.println("文件路径不存在!");
}else if(dir.isFile()) {
System.out.println("这是文件夹路径,请输入文件路径");
}
else {
//将文件夹路径对象返回
return dir;
}
}
}
//统计文件大小。返回值类型long,参数列表File dir
public static long getFileLength(File dir) {
//定义一个求和变量
long len =0;
//获取该文件夹下所有的文件和文件夹ListFiles
File [] subFiles =dir.listFiles();
//遍历数组
for (File subFile : subFiles) {
//判断如果是文件就计算大小并累加
if (subFile.isFile()) {
len +=subFile.length();
}else {
//如果是文件夹的话就在继续递归调用
len+=getFileLength(subFile);
}
}
return len;
}
}
효과는 다음과 같습니다.
재귀 운동 (3)
요구 사항 : 콘솔에서 경로를 입력하고 폴더를 삭제합니다.
public class Demo3_Test {
public static void main(String[] args) {
File file =getFile();
deleteFile(file);
}
//删除文件夹
public static void deleteFile(File dir) {
File[]subFiles=dir.listFiles();
//遍历数组
for (File subFile : subFiles) {
if (subFile.isFile()) {
//如果是文件夹就直接删除
subFile.delete();
}else {
deleteFile(subFile);
}
}
//循环结束后,把空文件夹删掉
dir.delete();
}
public static File getFile() {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入一个文件路径名称");
while (true) {
String line =scanner.nextLine();
File dir =new File(line);
if (!dir.exists()) {
System.out.println("文件路径不存在或输入有误");
}else if(dir.isFile()){
System.out.println("这是文件夹路径,请输入文件路径");
}else {
return dir;
}
}
}
}
재귀 운동 (4)
요구 사항 : 키보드에서이 개 폴더 경로를 수신하고, 다른 폴더로 폴더 (포함 내용) 중 하나에 복사합니다.
분석 :
- 대상 폴더에 원본 폴더 만들기
- 원본 폴더에있는 모든 파일과 폴더를 가져와 파일 배열에 저장합니다.
- 배열 탐색
- 파일 인 경우 io 스트림을 사용하여 읽고 쓰기
- 폴더 인 경우 재귀 적으로 호출
public class Demo4_Test {
public static void main(String[] args) throws IOException {
File src =getFile();
File desc =getFile();
if (src.equals(desc)) {
System.out.println("目标文件夹是原文件夹的子文件夹");
}else {
copy(src,desc);
}
}
//把其中一个文件夹中(包含内容)拷贝到另一个文件夹中
//返回值类型void
//参数列表File src,File desc
public static void copy(File src, File desc) throws IOException {
//在目标文件夹中创建原文件夹
File newDir =new File(desc,src.getName());
newDir.mkdir();
//获取原文件夹中所有的文件和文件夹,存储在File数组中
File[] subFiles =src.listFiles();
for (File subFile : subFiles) {
//如果是文件用io读写
if (subFile.isFile()) {
BufferedInputStream bis =new BufferedInputStream(new FileInputStream(subFile));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(new File(newDir,subFile.getName())));
int b;
while ((b=bis.read())!=-1) {
bos.write(b);
}
bis.close();
bos.close();
}else {
copy(subFile, newDir);
}
}
}
public static File getFile() {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入一个文件路径");
while (true) {
String line =scanner.nextLine();
File dir =new File(line);
if (!dir.exists()) {
System.out.println("文件路径不存在");
}
else if (dir.isFile()) {
System.out.println("这是文件夹路径,请输入文件路径");
}else {
return dir;
}
}
}
}
재귀 운동 (5)
요구 사항 : 수준별 인쇄, 키보드에서 폴더 경로 받기, 폴더의 모든 파일 및 수준별 폴더 이름 인쇄 (예 :
aaa는 폴더, bbb.txt, ccc.txt, ddd.txt 포함) 이 파일에는 eee에 eee, fff.txt 및 ggg.txt와 같은 폴더가 있으며 계층 구조를 인쇄합니다.
분석 :
1. 모든 파일 및 폴더와 반환 된 파일 배열
2를 가져 옵니다 . 어레이 이동
3. 파일이든 폴더이든 직접 인쇄해야합니다
.4. 폴더 인 경우 재귀 적으로 호출
public class Demo5_Test {
public static void main(String[] args) {
File dir =getFile();
printLev(dir,0);
}
public static void printLev(File dir ,int level) {
//把文件夹中的文件和文件夹放入File数组中
File[] subFiles =dir.listFiles();
for (File subFile : subFiles) {
for (int i = 0; i <=level; i++) {
System.out.print("\t");
}
//不论是文件还是文件夹,都需要直接打印
System.out.println(subFile);
//如果是文件夹,递归调用
if (subFile.isDirectory()) {
printLev(subFile,level+1);
//改变level++或者++level结果均不同
}
}
}
public static File getFile(){
Scanner scanner =new Scanner(System.in);
System.out.println("请输入一个文件路径");
while (true) {
String line =scanner.nextLine();
File dir =new File(line);
if (!dir.exists()) {
System.out.println("输入的文件路径不存在");
}else if (dir.isFile()) {
System.out.println("请输入一个文件路径");
}else {
return dir;
}
}
}
}
이러한 유형의 문제를 고려할 때 스택 문제를 고려해야합니다.
재귀 운동 (6)
요구 사항 : 피보나치 수열 수열
의 의미는 이전 두 항목 의 합이 현재 항목과 같다는 것입니다. an = an + 1 + an-2
public static int fun(int num) {
if (num ==1 || num==2) {
return 1;
}else {
return fun(num-2)+fun(num-1);
}
}
}
조셉 링
수요 : 행운의 숫자 찾기
public class Demo8_Test {
public static void main(String[] args) {
System.out.println(getLucklyNum(8));
}
public static int getLucklyNum(int num) {
ArrayList<Integer> list =new ArrayList<Integer>(); //创建集合存储1到num的对象
for (int i = 0; i < num; i++) {
list.add(i);
}
int count =1; //用于数数,只要是3的倍数就循环
for (int i = 0;list.size()!=1; i++) {
//只要集合中人数超过1,就不断地删除
if (i == list.size()) {
i=0; //重新归零
}
if (count%3==0) {
//如果是3的倍数就删除
list.remove(i--);
}
count++;
}
return list.get(0);
}
}