谈谈递归


1)递归是一种调用自身的编程技术,能够进行递归编程的关键是能够以递归的方式进行思考

2)任何递归的定义都必须包含一个称为基本条件的非递归部分,是递归最终能够终止,否则会导致无穷递归

3)递归编程:方法的每次递归调用都将创建新的局部变量和参数

4)在某些情况下,迭代方法显得极为复杂,对于某些问题,递归能够创建简短,高效的程序。

5)间接递归是指一个方法调用另一个方法,另一个方法又调用自己。或者嵌套更多层。


一个迷宫的例子:

用一个矩阵抽象表示迷宫,1,0表示可通过与不可通过,用递归来从迷宫的任意点搜索是否有到达终点(右下角为出口)的路径

package DiGui;

public class MazeSearch {

public static void main(String[] args) {

Maze maze
= new Maze();

System.out.println(
"the grid is :");
System.out.println(maze);
//自动调用toString方法

if(maze.successFrom(0, 0))
System.out.print(
"There is a path ");
else
System.out.println(
"There is no path!!!");

System.out.println(
"the path marked is:");
System.out.println(maze);
}
}



class Maze{

private final int TRIEDFAILD = 4;//将尝试过但没有成功的位置置为4
private final int PATH = 6;//将成功路径上的位置置为6

private int[][] grid = {//迷宫的矩阵表示
{1,0,0,0,1,1,0,1,0,1,1,1,1},
{
1,1,1,1,1,0,1,1,1,1,0,0,1},
{
0,0,0,1,0,0,1,0,1,0,1,0,0},
{
0,1,1,1,1,0,1,0,0,1,1,1,1},
{
0,1,1,0,1,0,1,1,0,1,1,1,1},
{
0,0,1,1,1,1,1,1,0,1,1,1,1},
{
1,0,0,0,0,0,0,1,1,1,1,1,1},
{
1,1,1,1,1,1,1,1,0,1,1,1,1},
};


public boolean valid(int row,int column){//某个位置是否为1,只有为1才有可能是通路
boolean result = false;
if((row >= 0 && row <= grid.length)&&(column >= 0 && column <= grid[0].length))
if (grid[row][column] == 1)
result
= true;
return result;
}


public boolean successFrom(int row,int column){//从点(row,column)位置能否找到通路
boolean done = false;
if(valid(row,column))
{
grid[row][column]
= TRIEDFAILD;//为1就先置为尝试过

if(row == grid.length-1 && column == grid[0].length-1)//递归结束条件
done = true;
else//递归的过程就在这,向下,右,上,左四个方向上按顺序递归(要防止数组越界)
{
if(row < grid.length -1)
done
= successFrom(row+1,column);
if(column < grid[0].length-1)
if(!done) done = successFrom(row,column+1);
if(row > 0)
if(!done) done = successFrom(row-1,column);
if(column < grid[0].length)
if(!done) done = successFrom(row,column-1);
}
if(done)
grid[row][column]
= PATH;//如果通过了就继续将尝试过升级为成功
}
return done;
}


public String toString(){//打印出通过之后的标记数组
String result = "\n";
for(int row = 0;row < grid.length;row ++)
{
for(int column = 0;column < grid[row].length;column ++)
result
+= grid[row][column] + "";
result
+= "\n";
}
return result;
}

}



执行结果:(用6替代原来的1标记一条通路,用4标记原来的1标记尝试过但最后没有路退回来的位置)


看了下书,写了个迷宫的小程序,其基本的思想就是,如果从一某个点能找到一条出路,那么从这个点的四个邻居点就一定至少有一个能找到出路,这样就去递归的找它的邻居点的路线。



--------------------------------------------------------------------------------------------------------------------------------------------------                        这是分割线,下面是别人的文章

--------------------------------------------------------------------------------------------------------------------------------------------------


下面是到bbs上找了几篇别人写的谈递归的文章:摘录精彩部分---

--------------------------------------------------------------------------------------------------------------------------------------------------

对一个输入的整数n,输出时从最低位开始每3位加上','。 
如输入:12345678 
输出:12,345,678 


想法一:把输入n的每一位都放在数组里面,然后看一共有多少位,把高几位(可能是1,2,3)输出出来,加上',',然后每输出3位数字之后输出一个',',当然还要考虑最低3位之后不用输出','。 

想法二:利用一个字符堆栈,不断的把最低位的字符n%10+'0'压入堆栈,每压入3个就压入一个',',n/=10,一直这样做下去,直到n为0,最后出栈,输出一个一个字符。 

想法三:n有多少位,假设有m位,那么可以先把前m-3位按照本题的方式输出,加上一个',',再输出最低3位,就完成了(!!以递归的方式思考问题。假设按本方式输出的一个函数为print(),则它可以这样定义: 
print(n){ 
print(n/1000);//n/1000为前m-3位 
输出','; 
输出后3位;//后3位为n%1000 


说说3种方法的优劣:想法一,考虑的细节比较多,容易出错,写起来憋屈;想法二和三,思路很清晰,二实现起来需要先实现1个堆栈,三则用了递归,自己写起来工作量少,憋屈给了计算机。 

按照方法三写了一下 
void print(int n){ 
if(n/1000>0){ 
print(n/1000); 
cout<<',';

         cout<<n%1000; 


输入1234,看见屏幕上出现1,234 


心里爽了一下,但是这里面有问题,当我们输入1000的时候,会输出1,0,为什么呢?看了下,原来我们输出n%1000,只是输出了n%1000的值而已,并不是把每一位都输出 
作出如下修改: 
void print(int n){ 
if(n/1000>0){ 
print(n/1000); 
cout<<',';

         cout<<(n%1000)/100; 
cout<<((n%1000)/10)%10; 
cout<<(n%1000)%10; 

分别输出百位十位个位上的数字,心想这下可好了,每位都输出了。 

兴奋的输入1000,发现屏幕上显示出001,000 
这倒是对了,可是最前面的1也变成了001,我们需要省略高位的0,经过思考,变成一下版本: 
void print(int n){ 
if(n/1000>0){ 
print(n/1000); 
cout<<',';

else{ 
cout<<n; 
return; 

         cout<<(n%1000)/100; 
cout<<((n%1000)/10)%10; 
cout<<(n%1000)%10; 

解释一下,因为当n/1000>0不成立的时候,说明现在要输出的n<1000,只用直接把n输出就好了,并且返回。 

到这里差不多了,总结一下这个例子带给我的启发 
使用递归,首先在逻辑上把问题划分成规模小的几个部分,其中有些部分的解法和本问题一样,然后写出大致的逻辑上的表示,第一部分怎么做,第二部分怎么做,一直到最后一部分,最后处理问题的细节。抛砖引玉,希望大家也说说自己的见解。 


以上by   ark@BMY  bbs

--------------------------------------------------------------------------------------------------------------------------------------------------

将复杂的处理归纳为较简单的处理,直到 最简单的处理。 
基础为归纳,即通过观察,得到3个内容: 1、递归的形式; 
                   2、最基本式是否有解决的方案; 
                   3、递归终止的条件 例子 

1 某人写了n封信和n个信封,如果所有的信都装错了信封。求所有的信都装错信封共有多少种不同情况。 归纳法例子 1.有n个硬币(n为偶数)正面朝上排成一排,每次将n-1个硬币翻成朝上为止。编程让计算机把翻硬币的最简过程及翻币次数打印出来(用*代表正面,用0代表反面)。 
基本形式:D[1]=0;d[2]=1 
递归式:d[n]= (n-1)*( d[n-1] + d[n-2]) 

3 梯有N阶,上楼可以一步上一价,也可以一次上二阶。编一个程序,计算共有多少种不同的走法。 
递归的形式:s[n]=s[n-1]+s[n-2] 
基本式子:s[1]=1;s[2]=2 


以上by  macintosh  @BMY bbs


------------------------------------------------------------------------------------------------------------------------------------------------





posted @ 2011-04-22 22:41  jinmengzhe  阅读(725)  评论(0编辑  收藏  举报