文章目录

一、概念

1、定义

所谓递归就是自己调用自己。

2、分类

递归分为两种:

  • 直接递归:方法自身调用自己。
  • 间接递归:A方法调用B方法,B方法调用C方法,C方法再调用A方法。
3、注意事项
  • 递归一定要有条件限定,保证递归能够停止下来,否则会形成死循环并发生栈内存溢出(StackOverflowError)。
  • 递归中虽然限定了停止下来的条件,但是递归次数不能太多,否则也会发生栈内存溢出。
  • 禁止构造方法递归。

二、递归的练习

1、练习:使用递归计算1-100的累加和
/**
* 递归练习:使用递归计算1-100的累加和
*
* @author zhuhuix
* @date 2020-05-31
*/
public class AddRecursion {
public static void main(String[] args) {
System.out.println(sum(100));
}

public static int sum(int n) {
if (n == 1) {
return 1;
} else {
return n + sum(n - 1);
}
}
}

输出:

java递归详解与应用_递归法


使用递归方法计算的原理图:

java递归详解与应用_递归计算_02

2、练习:使用递归计算10的阶乘
/**
* 递归练习:使用递归计算10!阶乘(1*2*3*4*...*10)的值
*
* @author zhuhuix
* @date 2020-05-31
*/
public class FactorialRecursion {
public static void main(String[] args) {
System.out.println(Factorial(10));
}
public static int Factorial(int n){
if (n==1){
return 1;
}else{
return n*Factorial(n-1);
}
}
}

输出:

java递归详解与应用_算法_03


原理:

java递归详解与应用_递归法_04

3、练习:使用递归列出windows目录下的所有文件夹及所有文件
/**
* 递归练习:使用递归列出windows目录下的所有文件夹及所有文件(不包括隐藏目录及文件)
*
* @author zhuhuix
* @date 2020-05-31
*/
public class FileRecursion {

public static void main(String[] args) {
getAllFile(new File("c:\\windows"));
}

public static void getAllFile(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
// 如果获取的File类型是目录,则进行递归调用
if (f.isDirectory()) {
System.out.println("目录:" + f);
getAllFile(f);
} else {
// 如果获取的File类型是文件,则直接打印输出
System.out.println("文件:" + f);
}
}
}
}
}

输出:

java递归详解与应用_java_05

三、递归的应用

1、快速排序
  1. 从数列中挑出一个元素,称为 “基准值”;
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区操作;
  3. 使用递归把小于基准值元素的子数列和大于基准值元素的子数列排序;
/**
* 快速排序--递归的应用
*
* @author zhuhuix
* @date 2020-05-31
*/
public class QuickSort {
public static void main(String[] args) throws ClassNotFoundException {
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 1000; i++) {
list.add(i);
}
// 随机打乱list
Collections.shuffle(list);
System.out.println("排序前:");
OriginalData.printList(list);

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
Long start = System.currentTimeMillis();
System.out.println("排序开始时间:" + sdf.format(start));
Long end = System.currentTimeMillis();
System.out.println("排序结束时间:" + sdf.format(end));

List<Integer> sortList=quickSort(list,0,list.size()-1);

System.out.println("排序耗用了" + (end - start) + "毫秒");
System.out.println("排序后:");
OriginalData.printList(sortList);
}

// 使用递归实现快速排序
private static List<Integer> quickSort(List<Integer> list, int left, int right) {
if (left < right) {
int partitionIndex = partition(list, left, right);
quickSort(list, left, partitionIndex - 1);
quickSort(list, partitionIndex + 1, right);
}
return list;
}

private static int partition(List<Integer> list, int left, int right) {
int pivot = left;
int index = pivot + 1;
for (int i = index; i <= right; i++) {
if (list.get(i) < list.get(pivot)) {
swap(list, i, index);
index++;
}
}
swap(list, pivot, index - 1);
return index - 1;
}

private static void swap(List<Integer> list, int i, int j) {
int temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}


}

输出:

java递归详解与应用_递归_06