一、递归的核心思想就是自己调用自己,一般来说能够用递归解决的问题应满足3个条件:
1.需要解决的问题可以转化为一个或多个子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量和规模上不同。
2.递归调用的次数必须是有限的。
3.必须有结束递归的条件来终止递归。
二、何时使用递归?
1.定义是递归的
有许多数学公式、数列和概念的定义是递归的。比如求n!,Fibonacci数列等。这些问题的求解过程是可以将其递归定义直接转化为对应的递归算法的。
比如求 n!
int fun(int n) { if(n==1) { //递归头 return(1); } else { //递归体 return (fun(n-1)*n); } }
2.有些数据结构是递归的
单链表就是一种递归数据结构,其结点类型定义如下:
typedef struct LNode { ElemType data; struct LNode *next; }LinkList;
求一个不带头结点的单链表L所有的data域(假设为int类型)之和的递归算法如下:
int Sum(LinkList *L) { if (L == NULL) { return 0; } else { return(L->data+sum(L->next)); } }
3.问题的求解方法是递归的
比如汉诺塔问题:
三、递归的不足
简单的程序使递归的优点之一,但是递归调用会占用大量的系统堆栈,在递归调用层次多时速度要比循环慢的多,所以在使用递归时要慎重。
package day6; //递归的基本思想就是自己调用自己 public class digui { public static void main(String[] args) { long d1 = System.currentTimeMillis(); System.out.printf("%d的阶乘的结果:%s%n",10,factorial(10)); long d2 = System.currentTimeMillis(); System.out.printf("递归费时:%s%n",d2-d1); factorialLoop(10); } static long factorial(int n) { if(n==1) {//递归头 return 1; } else {//递归体 return n*factorial(n-1);//n! = n*(n-1)! }//1*2*3*4...*10 } static long factorialLoop(int a) { long d3 = System.currentTimeMillis(); long result = 1; while(a>1) { result *= a*(a-1); a = a-2; } long d4 = System.currentTimeMillis(); System.out.println("普通循环阶乘结果:"+result); System.out.printf("循环费时%s%n",d4-d3); return result; } }