二十四桥仍在,波心荡、冷月无声。
——姜夔《扬州慢》
 
递归 
递归 :指在当前方法内调用自己的这种现象,每次调用时传入不同的变量。
 
1. 计算 1+2+3+….+n的和 1 2 3 4 5 6 7 8 9 10 11 12 13 @Test public  void  test2 ()   {    int  n = 100 ;     int  sum = sum( n );     System.out.println( "sum = "  + sum ); } public  int  sum (int  n)   {    if  (n == 1 ) {         return  1 ;     }     return  sum( n - 1  ) + n; } 
 
2. 递归阶乘 1 2 3 4 5 6 7 8 9 10 11 12 @Test public  void  test3 ()   {    int  n = 10 ;     int  value = getValue( n );     System.out.println( "value = "  + value ); } private  int  getValue (int  n)   {    if  (n == 1 ) {         return  1 ;     }     return  getValue( n - 1  ) * n; } 
 
3. 斐波那契数列 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   @Test    public  void  test4 ()   {       int  n = 10 ;       int  sum = getRabbit( n );       System.out.println( "sum = "  + sum );   }   private  int  getRabbit (int  n)   {       if  (n == 1  || n == 2 ) {           return  1 ;       }       return  getRabbit( n - 1  ) + getRabbit( n - 2  );   } 
 
4. 爬山问题 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 29 30 31 32 33 34 35        @Test      public  void  test5 ()   {         int  num = 40 ;         int  value = getTimes( num );         System.out.println( "value = "  + value );     }     private  int  getTimes (int  num)   {         if  (num == 1 ) return  1 ;         if  (num == 2 ) return  2 ;         if  (num == 3 ) return  4 ;         return  getTimes( num - 1  ) + getTimes( num - 2  ) + getTimes( num - 3  );     } } 
 
5. 打印多级目录 
分析 :多级目录的打印,就是当目录的嵌套。遍历之前,无从知道到底有多少级目录,所以我们还是要使用递归实
现。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24        @Test     public  void  test ()  {        File file = new  File("E:" );        printDir(file);    }      private  void  printDir (File file)   {                File[] files = file.listFiles();        if (files!=null ){                        for  (File file1 : files) {                   if (file1.isFile()) {                        System.out.println(file1.getName() );                    }else {                        printDir(file1);                    }                }        }    } 
 
6. 递归的调用机制图解 
6.1 递归能解决的问题 
各种数学问题: 8 皇后问题 , 汉诺塔, 阶乘问题, 迷宫问题, 球和篮子的问题(google 编程大赛) 
各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等. 
将用栈解决的问题–>第归代码比较简洁 
 
 
6.2 递归需要遵循的重要规则 
执行一个方法时,就创建一个新的受保护的独立空间(栈空间) 
方法的局部变量是独立的,不会相互影响, 比如 n 变量 
如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据. 
递归 必须向退出递归的条件逼近,否则就是无限递归,出现 StackOverflowError,死龟了:) 
当一个方法执行完毕,或者遇到 return,就会返回, 遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕 
 
 
7. 递归-迷宫问题 7.1 创建地图及测试 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public  class  MiGong   {	public  static  void  main (String[] args)   { 		 		int [][] map = new  int [8 ][7 ]; 		 		 		 		for  (int  i = 0 ; i < map.length; i++) { 			map[i][0 ]=1 ; 			map[i][6 ]=1 ; 		} 		 		 		for  (int  i = 0 ; i < 7 ; i++) { 			map[0 ][i] = 1 ; 			map[7 ][i] = 1 ; 		} 		 		 		map[3 ][1 ] = 1 ; 		map[3 ][2 ] = 1 ; 		map[2 ][2 ] = 1 ; 		map[5 ][2 ] = 1 ; 		map[5 ][3 ] = 1 ; 		map[5 ][4 ] = 1 ; 		 		System.out.println("输出地图:" ); 		for  (int  i = 0 ; i < map.length; i++) { 			for  (int  j = 0 ; j < map.length-1 ; j++) { 				System.out.print(map[i][j]+" " ); 			} 			System.out.println(); 		} 		 		 		 		setWay2(map, 1 , 1 ); 		 		System.out.println("找到的路的地图:" ); 		for  (int  i = 0 ; i < map.length; i++) { 			for  (int  j = 0 ; j < map.length-1 ; j++) { 				System.out.print(map[i][j]+" " ); 			} 			System.out.println(); 		} 		 	 	} } 
 
7.2 策略一 
策略(方法) 下->右->上->左 
 
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public  static  boolean  setWay (int [][] map,int  i,int  j)   {	 	 	if (map[6 ][5 ]==2 ) { 		return  true ; 	}else  { 		 		 		if (map[i][j] == 0 ) { 			 			map[i][j] = 2 ; 			 			if (setWay(map, i+1 , j)) { 				return  true ; 			}else  if (setWay(map, i, j+1 )) { 				return  true ; 			}else  if  (setWay(map, i-1 , j)) { 				return  true ; 			}else  if  (setWay(map, i, j-1 )) { 				return  true ; 			}else  { 				map[i][j] = 3 ; 				return  false ; 			} 		 		}else  { 			return  false ; 		} 		 	} } 
 
7.3 策略二 
策略假定(方法) 上->右->下->左 走
 
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 29 30 31 32 33 34 35 public  static  boolean  setWay2 (int [][] map,int  i,int  j)   {		 		 		if (map[6 ][5 ]==2 ) { 			return  true ; 		}else  { 			 			 			if (map[i][j] == 0 ) { 				 				map[i][j] = 2 ; 				 				if (setWay2(map, i-1 , j)) { 					return  true ; 				}else  if (setWay2(map, i, j+1 )) { 			 					return  true ; 				}else  if  (setWay2(map, i+1 , j)) { 					 					return  true ; 				}else  if  (setWay2(map, i, j-1 )) { 			 					return  true ; 				}else  { 					map[i][j] = 3 ; 					return  false ; 				} 			 			}else  { 				return  false ; 			} 			 		}	 	} 
 
8. 递归-八皇后问题 
第一个皇后先放第一行第一列 
第二个皇后放在第二行第一列、然后判断是否 OK, 如果不 OK,继续放在第二列、第三列、依次把所有列都 放完,找到一个合适 
继续第三个皇后,还是第一列、第二列……直到第 8 个皇后也能放在一个不冲突的位置,算是找到了一个正确 解 
当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解, 全部得到. 
然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4 的步骤 
 
 
8.1 三个方法解决八皇后问题 
private boolean judge(int n); 
private void print() ;将皇后摆放的位置输出 
private void check(int n);check 是 每一次递归时,进入到 check 中都有 for(int i = 0; i < max; i++),因此会有回溯 
 
 
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 	private  boolean  judge (int  n)   { 		judgeCount++; 		 		 		for  (int  i = 0 ; i < n; i++) { 			if (array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n]-array[i])) { 				return  false ; 			} 		} 		 		return  true ; 	} 	 	 	 	private  void  print ()   { 		count++; 		for  (int  i = 0 ; i < array.length; i++) { 			System.out.print(array[i]+1 +" " ); 		} 		System.out.println(); 	} 	 	 	private  void  check (int  n)   { 		 		if (n == max){ 			print(); 			return ; 		} 		 		 		for  (int  i = 0 ; i < max; i++) { 			 			 			array[n]= i;  			 			 			if (judge(n)) { 				check(n+1 ); 			} 			 			 		} 		 	} 
 
8.2 测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  class  Queue8   {	 	 	int  max = 8 ; 	 	int [] array = new  int [max]; 	 	static  int  count = 0 ; 	static  int  judgeCount = 0 ; 	public  static  void  main (String[] args)   { 		 		Queue8 queue8 = new  Queue8(); 		queue8.check(0 ); 		System.out.println(); 		System.out.printf("一共有%d解法\n" ,count); 		System.out.printf("一共有%d次判断" ,judgeCount); 	} }