递归相当于数球游戏:
一个队人排成一排站好,每个人手里有几个球,球数不定。
我站在队伍的最后,有一个人问题我:队伍里一共有多少球?我不知道总数,只知道自己手里有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);
}
}
}
}
用Python实现:
def bin_search(lst, target, low, high):
while low < high:
mid = (low + high) // 2
if target > lst[mid]:
low = mid + 1
elif target < lst[mid]:
high = mid - 1
else:
return mid
return -1
a = [1,34,354,345,4,44,8,465,33,45]
a.sort()
print(bin_search(a, 345, 0, len(a)-1))