.

计算机编程必备技巧使用递归

中科医院专家 https://m.39.net/baidianfeng/qwzj/

1、引言

今天我们来学习递归,如果单说学习算法,递归并不能说是算法,而是一种编程的手法,为什么现在要学习这个呢?因为后面在学习其他算法时,要牵涉一些递归的调用方法,是为以后理解学习的内容做好铺垫。

递归方法作为一种优雅的解题方法,是大多数程序员比较喜欢的编写方式之一。递归把程序员分为三类:一种是恨它的,第二种是爱它的,最后一种是恨了一段时间之后接触之后又爱上了它。我平时编写代码的时候可能很少用到,但我对递归的印象还是蛮喜欢的。今天就来比较深入的学习一下递归的相关知识吧。

2、递归

2.1.1什么是递归

递归说白了就是用一个函数不断调用自己的过程,递归的使用可以让代码逻辑很清晰,但并没有实质性能的提升。实质上,在有些情况下,使用循环的性能可能会更佳。

2.1.2递归中的两大元帅

上面介绍到递归是一个函数不断调用自己的过程,但如果没有限制结束调用的条件,就会让递归无限的循环下去。于是编写递归函数时,必须告诉函数什么时候要停止递归调用。这就引出了递归的两大元帅,分别为基线条件(basecase)和递归条件(recursivecase)。递归条件是指让函数调用自身,而基线条件就是通知函数不要再调用自己,从而避免了无限循环。

2.2.1栈

使用递归必须需要了解栈的概念,栈是一种简单的数据结构,它的特点可以举一个简单的例子你就明白了。在餐厅吃饭的时候,我们通常是在收银台进行点餐,然后点餐付款成功之后会将信息传送给后厨师傅手里,以一个先来后到的原则,厨师每次看到的信息都是最早来点餐的人的信息,而且做完之后便删掉了这个点餐信息,接着去做下一个人点的餐,而收银员每回都只在待做餐列表中添加点餐信息,而不管究竟现在有多少点餐信息。因此这个待做餐列表就只有两种操作:存入和删除。栈这种数据结构就是这么一个工作原理,理解了这个原理之后,我们就可以继续后面的内容了。

2.2.2调用栈

计算机在内部使用被称为调用栈的栈。以一段代码解释一下计算机是如何调用栈的。

publicstaticvoidmain(String[]args){

//调用方法1

Greet(努力的浩浩);

}

//定义一个问候的方法1

privatestaticvoidGreet(Stringname){

System.out.println(hello,+name+!);

Greet2(name);

System.out.println(gettingreadytosaybye);

bye();

}

//定义一个问候的方法2

privatestaticvoidGreet2(Stringname){

System.out.println(howareyou,+name+?);

}

//定义一个再见的方法

privatestaticvoidbye(){

System.out.println(ok,bye!);

}

下面详细介绍调用函数时内存的变化情况。

如main方法中调用了Greet(努力的浩浩);计算机会为该方法开辟一块内存空间,且存储变量name的值为努力的浩浩,接下来执行该方法,打印出hello,努力的浩浩!之后,程序开始执行Greet2的方法。

当然,计算机也会为这个方法开辟一块内存空间,并且存储变量name的值为努力的浩浩。那么这两个方法执行的过程中,计算机就开辟了两个内存单元,于是乎计算机采用栈存储这些内存块,其中第二个内存单元位于第一个内存块的上方,打印出howareyou,努力的浩浩?之后,从Greet2()方法中返回,此时,栈顶被弹出,于是Greet()中的变量成为了栈顶,而继续执行程序,应先打印出gettingreadytosaybye之后,再调用bye()打印出ok,bye!的语句。

上面这个栈由于存储了多个函数的变量,称为了调用栈。

2.2.3递归调用栈

递归函数其实也是使用的是调用栈,我们先来定义一个递归函数,该函数完成的功能就是求数的阶乘,函数名为factorial,

如factorial(5)记作5!,其定义为5!=5x4x3x2x1。下面是递归函数阶乘的代码!

//定义一个递归函数阶乘

privatestaticintfactorial(intnumber){

if(number==1)

{

return1;

}

else{

returnnumber*factorial(number-1);

}

}

下面以一幅图来讲解递归调用栈的原理,详细分析fact(3)调用栈是如何变化的。

第一次调用第二次调用返回

2.3温馨提示

使用栈虽然很方便,但是也有很大代价:如果要存储信息可能需要大量内存,每个函数调用都将占用内存,如果栈摞的很高必将

导致计算机存储大量函数调用的信息。这个时候怎么办呢?

有两种解决方案:

1、使用循环

2、使用尾递归(这个我也不懂是啥,书上就是这么写的,并非所有编程语言都支持尾递归)




转载请注明:http://www.abachildren.com/sstx/7532.html