递归

递归
一、递归简介

使用递归就是使用递归方法(recursive method)编程,递归方法就是直接或间接调用自己的方法。
递归方法的特点
这些方法使用if-else或switch语句会导致不同的情况
一个或多个基础情况用来停止递归
每次递归都会简化原始问题,让它不断地接近基础情况,直到它变为基础情况
二、两个基础递归问题:

1.计算阶乘

阶乘的定义:

0!=1;

n!=n*(n-1)21=n(n-1)!; (n>0)

复制代码
1 import java.util.Scanner;
2 public class ComputeFactorial{
3 public static void main(String[] args){
4 Scanner input=new Scanner(System.in);
5 System.out.print(“Enter a nonnegtive integer:”);
6 int n=input.nextInt();
7 System.out.println(n+"!="+factorial(n));
8 }
9 private static int factorial(int n){
10 if(n==0)
11 return 1;
12 else
13 return n*factorial(n-1);
14 }
15 }
复制代码
2.计算斐波那契数

斐波那契数的定义:

fib(0)=0;

fib(1)=1;

fib(index)=fib(index-1)+fib(index-2); index>=2

复制代码
1 import java.util.Scanner;
2 public class ComputeFibonacci{
3 public static void main(String[] args){
4 Scanner input=new Scanner(System.in);
5 System.out.print(“Enter an index for Fobonacci number:”);
6 int n=input.nextInt();
7 System.out.println(fib(n));
8 }
9 private static int fib(int n){
10 if(n0)
11 return 0;
12 else if(n
1)
13 return 1;
14 else
15 return fib(n-1)+fib(n-2);
16 }
17 }
复制代码
以上两个例子只是用来演示递归的概念,实际上用循环来实现效率更高,代码如下:

复制代码
1 //阶乘
2 import java.util.Scanner;
3 public class ComputeFactorial{
4 public static void main(String[] args){
5 Scanner input=new Scanner(System.in);
6 System.out.print(“Enter a nonnegtive integer:”);
7 int n=input.nextInt();
8 int n0=n;
9 int s=1;
10 while(n>0)
11 {
12 s*=n–;
13 }
14 System.out.println(n0+"!="+ s);
15 }
16 }

复制代码
复制代码
1 //斐波那契数
2 import java.util.Scanner;
3 public class ComputeFibonacci{
4 public static void main(String[] args){
5 Scanner input=new Scanner(System.in);
6 System.out.print(“Enter an index for Fobonacci number:”);
7 int n=input.nextInt();
8 int f0=0,f1=1,currentFib=0;
9 for(int i=2;i<=n;i++){
10 currentFib=f0+f1;
11 f0=f1;
12 f1=currentFib;
13 }
14 System.out.println(currentFib);
15 }
16 }
复制代码
三、递归的辅助方法

1.递归的辅助方法

用递归的思路解决回文字符串问题:

复制代码
1 import java.util.Scanner;
2 public class Palindrome{
3 public static void main(String[] args){
4 Scanner input=new Scanner(System.in);
5 System.out.print(“Enter a string:”);
6 String text=input.nextLine();
7 System.out.println(isPalindrome(text));
8 }
9 private static boolean isPalindrome(String text){
10 if(text.length()<=1)
11 return true;
12 else if(text.charAt(0)!=text.charAt(text.length()-1))
13 return false;
14 else
15 return isPalindrome(text.substring(1,text.length()-1));
16 }
17
18 }
复制代码
由于每次递归时都要创建一个新的字符串,因此不够高效。为避免创建新字符串,可以使用low和high下标来表明子串的范围。

复制代码
1 import java.util.Scanner;
2 public class Palindrome{
3 public static void main(String[] args){
4 Scanner input=new Scanner(System.in);
5 System.out.print(“Enter a string:”);
6 String text=input.nextLine();
7 System.out.println(isPalindrome(text));
8 }
9 private static boolean isPalindrome(String text){
10 return isPalindrome(text,0,text.length()-1);
11 }
12 private static boolean isPalindrome(String text,int low,int high){
13 if(low>=high)
14 return true;
15 else if(text.charAt(low)!=text.charAt(high))
16 return false;
17 else
18 return isPalindrome(text,low+1,high-1);
19 }
20
21 }
复制代码
程序中定义了两个重载的isPalindrome方法,第一个方法将low和high的值传递给第二个方法,第二个方法采用递归调用,检测不断缩小的子串是否回文。在递归程序设计中定义第二个方法来接收附加的参数是一种常用的技巧,称为递归的辅助方法。

2.递归的辅助方法举例

选择排序

复制代码
1 public class RecursiveSeletionSort{
2 public static void sort(double[] list){
3 sort(list,0,list.length-1);
4 }
5 public static void sort(double[] list,int low,int high){
6 if(low<high){
7 int indexOfMin=low;
8 double min=list[low];
9 for(int i=low+1;i<=high;i++){
10 if(min<list[i]){
11 min=list[i];
12 indexOfMin=i;
13 }
14 }
15 //Swap
16 list[indexOfMin]=list[low];
17 list[low]=min;
18
19 sort(list,low+1,high);
20 }
21 }
22 }//只是算法,并非完整程序
复制代码
二分查找

复制代码
1 public class RecursiveBinarySearch{
2 public static int binarySearch(int[] list,int key){
3 int low=0;
4 int high=list.length-1;
5 return binarySearch(list,key,low,high);
6 }
7 public static int binarySearch(int[] list,int key,int low,int high){
8 if(low>high)
9 return -low-1;
10 int mid=(low+high)/2;
11 if(key<list[mid])
12 return binarySearch(list,key,low,mid-1);
13 else if(key=list[mid])
14 return mid;
15 else
16 return binarySearch(list,key,mid+1,high);
17 }
18 }//只是算法,并非完整程序
复制代码
四、尾递归

如果从递归调用返回时没有待定的操作要完成,这个递归就称为尾递归(tail recursive)。某些编译器会优化尾递归以减少桟空间。可以使用辅助参数将非尾递归转化为尾递归。

将阶乘的例子改为尾递归

五、更多例子

1.求出目录的大小

复制代码
1 package book;
2
3 import java.io.File;
4 import java.util.Scanner;
5
6 public class DirectorySize{
7 public static void main(String[] args){
8 System.out.print(“Enter a directory or a file:”);
9 Scanner input=new Scanner(System.in);
10 String directory=input.nextLine();
11
12 System.out.println(getSize(new File(directory))+“bytes”);
13
14 input.close();
15 }
16 public static long getSize(File file){
17 long size=0;
18 if(file.isDirectory()){
19 File[] files=file.listFiles();
20 for(int i=0;i<files.length;i++){
21 size+=getSize(files[i]);
22 }
23 }
24 else
25 size+=file.length();
26
27 return size;
28 }
29
30 }
复制代码
2.汉诺塔问题

复制代码
1 import java.util.Scanner;
2 public class TowersOfHanoi{
3 public static void main(String[] args){
4 Scanner input=new Scanner(System.in);
5 System.out.print(“Enter number of disks:”);
6 int n=input.nextInt();
7 System.out.println(“The moves are:”);
8 moveDisks(n,‘A’,‘B’,‘C’);
9 }
10 private static void moveDisks(int n,char fromTower,char toTower,char auxTower){
11 if(n==1)
12 System.out.println("Move disk “+n+” from “+fromTower+” to "+toTower);
13 else{
14 moveDisks(n-1,fromTower,auxTower,toTower);
15 System.out.println("Move disk “+n+” from “+fromTower+” to "+toTower);
16 moveDisks(n-1,auxTower, toTower,fromTower);
17
18 }
19
20 }
21
22 }
复制代码
3.八皇后问题

复制代码
1 import java.awt.;
2 import javax.swing.
;
3 public class EightQueens extends JApplet{
4 /**
5 *
6 /
7 private static final long serialVersionUID = 5660619297259886927L;
8 public static final int SIZE=8;
9 private int[] queens=new int[SIZE];
10
11 public EightQueens(){
12 search(0);
13 add(new ChessBord(),BorderLayout.CENTER);
14 }
15
16 private boolean isValid(int row,int cloumn){
17 for(int i=1;i<=row;i++){
18 if(queens[row-i]==cloumn
19 ||queens[row-i]==cloumn-1
20 ||queens[row-i]cloumn+1)
21
22 return false;
23 }
24 return true;
25 }
26
27 private boolean search(int row){
28 if(row
SIZE)
29 return true;
30
31 for(int cloumn=0;cloumn<SIZE;cloumn++){
32 queens[row]=cloumn;
33 if(isValid(row,cloumn)&&search(row+1))
34 return true;
35 }
36
37 return false;
38 }
39
40 class ChessBord extends JPanel{
41 /
*
42 *
43 /
44 private static final long serialVersionUID = 4151757353625344600L;
45 private Image queenImage=new ImageIcon(“image/queen.jpg”).getImage();
46
47 ChessBord(){
48 this.setBorder(BorderFactory.createLineBorder(Color.BLACK,2));
49 }
50 protected void paintComponent(Graphics g){
51 super.paintComponent(g);
52
53 //Paint the queens
54 for(int i=0;i<SIZE;i++){
55 int j=queens[i];
56 g.drawImage(queenImage,j
getWidth()/SIZE,igetHeight()/SIZE,getWidth()/SIZE,getHeight()/SIZE,this);
57 }
58
59 //Draw the horizontal and vertical lines
60 for(int i=0;i<SIZE;i++){
61 g.drawLine(0,i
getHeight()/SIZE,getWidth(),igetHeight()/SIZE);
62 g.drawLine(i
getWidth()/SIZE,0,i*getWidth()/SIZE,getHeight());
63 }
64
65 }
66 }
67 }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值