递归

来源:互联网 发布:软件开发的难度 编辑:程序博客网 时间:2024/06/16 09:29
递归相当于数球游戏:

一个队人排成一排站好,每个人手里有几个球,球数不定。

我站在队伍的最后,有一个人问题我:队伍里一共有多少球?我不知道总数,只知道自己手里有2个球。因此我去问倒数第二个herry,到他为止,前面的人一共有多少球。herry也不知道,只知道自己手里有3个球。于是他去问倒数第三个人mary,mary有1个球,她去问倒数第4个人。。。这样一直传递到队伍第一个人,他手里的球数,就能算出队伍里的总球数了。


我们把上例中“询问”当做一个递归方法。我们在计算的过程中反复的调用这个方法(反复的询问前面的人),但是每一次调用都缩小了要解决的问题的范围(队伍前面未被询问过的人越来越少,也越来越接近最终的答案)。


因此递归有三个特点:

1,调用自身。

2,当它调用自身时,是为了解决更小的问题。

例如上例中,所有人都符合:到我为止的总球数=我前面所有人的总球数+我的球数

我前面所有人的总球数 就是比 到我为止的总球数 更小的问题。

而递归将不断的循环调用更小的问题,直到问题缩小到下面说的base case.

3,递归有一个根,也就是上例中的队伍第一个人。这个人不需要再问其他人了,询问到这个人时,循环就可以终止了。如果没有这样的终止条件,递归将溢出。

这个根一般是类似:

if (n==0){

  return 0; //如果一个人都没有,那么总数就是0.

}

导致递归的方法返回而没有再一次的递归调用,我们称之为基值情况(base case)。每一个递归调用都必须有一个基值条件,以避免循环无限制的进行下去。


这里需要说明的是,直到最内层(base case)的调用返回前,递归了多少次,就有多少个对象同时存在(这对象的输入参数和返回地址都会被压入一个栈)。因此递归是一种效率比较低的方法。时间和空间的消耗都比较大。


下面我们来看一个使用递归的例子:

在有序数组中,用二分法查找数据的代码。 方法find()用循环,方法recFind()用递归。

public class App {    public static void main(String[] args) {        System.out.println(App.recFind(4,0,testArray.length-1));    }        static int[] testArray = {2,3,4,5,6,7,8,10,13,15,16,19,21,34};        private static int find(int searchKey, int lowBounder, int highBounder){        int currentKey=0;                while(true){            currentKey = (lowBounder + highBounder)/2;            if (testArray[currentKey] == searchKey){                return currentKey;            }            else if (lowBounder > highBounder){                return testArray.length;            }            else{                if (testArray[currentKey] < searchKey){                    lowBounder = currentKey + 1;                }else{                    highBounder = currentKey - 1;                }            }                    }            }        private static int recFind(int searchKey, int lowBounder, int highBounder){        int currentKey = (lowBounder + highBounder)/2;                    if (testArray[currentKey] == searchKey){                return currentKey;            }            else if (lowBounder > highBounder){                return testArray.length;            }            else{                if (testArray[currentKey] < searchKey){                    return recFind(searchKey, currentKey+1, highBounder);                }                else{                    return recFind(searchKey, lowBounder, currentKey-1);                }            }            }}



原创粉丝点击