递归
本词条由“科普中国”百科科学词条编写与应用工作项目 审核 。
程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
以上,是百度百科给出的定义。
简单点,就是: 递归是一种重要的编程技术。该方法用于让一个函数从其内部调用其自身。
经典递归实例
1、阶乘
在计算机科学里标志性的递归实例就是阶乘函数。对于一个正数的阶乘如下:
factorial(n) = 1 * 2 * 3 * ...... * (n-1) * n
下面,用Js实现的一个求阶乘函数:
/*
*
* 返回n的阶乘。先决条件: n为一个非负整数
* */
var factorial = function(n) {
return n <= 1 ? 1 : factorial(n-1) * n;
};
2、最大公约数
求最大公约数的一个算法是:一个值要能整除a和b,那它也必能整除 a-b。
算法Js实现代码如下 :
/*
*
* 返回a和b的最大公约数,先决条件是:a和b都是非负整数
* */
var gcd = function (a, b) {
if ( a === b ) {
return a;
} else if ( a < b ) {
return gcd(a, b-a);
} else {
return gcd(a-b, b);
}
};
或者,使用条件表达式:
/*
*
* 返回a和b的最大公约数,先决条件是:a和b都是非负整数
* */
var gcd = function (a, b) {
return a === b ? a : a < b ? gcd(a, b-a) : gcd(b, a-b);
};
3、汉诺塔
将n个盘子从A栈移到B栈,需要首先将n-1个盘子移到临时栈C,然后经底下的盘子由A移到B,最后经n-1个盘子由C移到B。
Js实现:
/*
* 显示完成以下任务的HTML指令,以塔a为临时存储位置,
* 将n个盘子由塔a移到塔b.
* 先决条件: n是整数,a、b、c为不同的字符串
*
* */
var hanoi = function(n, a, b, c) {
if ( n !== 0 ) {
hanoi(n-1, a, c, b);
document.write("Move from" + a + "to" + b "<br />");
hanoi(n-1, c, b, a);
}
};
4、二分查找
/*
* 返回数值 X 在数组a中的索引位置。若X不在a中,则返回-1。
* 前提条件: 数组a是有序的。
*
* @param {array} a - 数组
* @param {number} X - 待查找数
* */
var binarySearch = function (a, x) {
/*
* 返回数值X在数组中的索引位置
* 介于索引first(含)和last(不含)中间
* */
var search = function (first, last) {
// 如果范围为空,那就是没找到
if ( first >= last ) {
return -1;
}
// 查找中间点,必须时进行递归
var mid = Math.floor((first + last) / 2);
if ( a[mid] === x ) {
return mid;
} else if ( a[mid] < x ) {
return search(mid+1, last);
} else {
return search(first, mid);
}
};
// 在整个 a 中查找 X
return search(0, a.length);
};
5、递归与家族树
编写程序,来判断一个人是否是另一个人的祖先。
/*
* @Constructor
* */
var Person = function(name, mother, father) {
this.name = name;
this.mother = mother;
this.father = father;
};
/*
* 如果他是P的祖先,则返回true, 否则返回false.
* 前提条件: 必须先构建家族树,仅包含人员对象
* 或null,不存在循环。
* */
var Person.prototype.isAncestorOf = function(p) {
return p != null && (this === p.mother ||
this === p.father ||
this.isAncestorOf(p.mother) ||
this.isAncestorOf(p.father));
};