J2SE快速进阶——递归算法

递归算法

递归,百度百科对其定义为:程序调用自身的编程技巧。说白了就是一个函数或者过程在执行时会调用自身。

先用一个 “ 求一个数的阶乘 ” 的例子来说明 :

public class Test {
	public static void main(String[] args) {
		System.out.println(Method(3));
	}
	public static int Method(int n){
		if(n==1)
			return 1;
		else
			return n*Method(n-1);
	}
}

由程序可知,Method()函数的作用为计算参数n的阶乘,当n的值为1时,直接返回结果为1;否则执行else下的语句,重新调用Method()函数,期执行过程如下:

当n=3时,执行else下的return 3*Method(2),Method(2)即以2为实参重新调用了函数Method()本身;同理,n=2时,执行else下的return 2*Method(1);n=1时,直接返回1。

到了这里会发现,递归可以把一个大型、复杂的问题层层转化为一个与原问题相似的的规模较小的问题来求解,只需要少量的程序代码就可以描述出解题过程需要的多次重复计算,大大减少了程序的代码量。

递归有以下特点:

1、递归实现时,是把一个问题转化为类似的规模较小的问题,而这个新的问题与原问题的解决方法相同,只是处理对象不同,通过多次递归得出最简单的解,然后逐层向上返回调用,得到最终解。;

2、递归要有结束条件,用来终止循环调用,即当满足这个条件时,就不再进行递归,否则一直调用本身,知道满足这个条。(上例中的if(n==1)就是结束条件)

3、虽然递归在一定程度上使代码达到复用,但深层次的递归会涉及到频繁进栈出栈和分配内存空间,所以运行效率比较低,当问题规模较大时,不推荐使用。

4、在递归过程中,每次调用中的参数,方法返回点,局部变量都是存放在堆栈中的,如果当问题规模非常大时,容易造成堆栈溢出。

递归实现的实例

为了加深印象,这里分享几个可以用递归来实现的小例子

1、求1+2+3+……+100 的和

public class Sum {
	public static void main(String[] args) {
		System.out.println(sum(100));
	}
	public static int sum(int num){
        if(num <= 0){
        	return 0;                //当num=0时,循环结束
        }else{
        	return num + sum(num-1); //调用递归方法
        }
 }    

2、十进制数转化为二进制数

public class DecimalToBinary {
	public static void main(String[] args) {
		DecimalToBinary(118);
	}
	public static void DecimalToBinary(int num){
        <span style="white-space:pre">	</span>if(num ==0){                    //当num=0时,循环结束
               <span style="white-space:pre">	</span>       return;
       <span style="white-space:pre">	</span>        }else{
                      DecimalToBinary(num/2);  //调用递归方法
                      System.out.print (num%2);
       <span style="white-space:pre">	</span>        }
        }
}

3、计算斐波那契数列

public class Fibonacci{
	public static void main(String[] args) {
		System.out.println(fib(4));
	}
   static int fib(int n)
	{
	   if(n==0||n==1)
	       return n;
	   else
	       return fib(n-1)+fib(n-2);
	}
}

递归与迭代的区别

一些初学者有时可能会把递归和迭代这两种算法混淆,递归是一个函数(或过程)通过不断对自己的调用而求得最终结果的一个算法,迭代则可以看做循环。

文章开头的例子可以用迭代实现如下:

public class Test {
	public static void main(String[] args) {
		System.out.println(Method(3));
	}
	public static int Method(int n){
		int product=1;
		for(int i=n;i>0;i--){
			product=product*i;
		}
		return product;
	}
}

从代码中可以发现,迭代只是单纯的循环,从i=n一直循环到i=1,最后直接返回最终解product即可;而递归则是把亟待解决的问题转化成为类似的规模较小的问题,通过多次递归得出最简单的解,然后逐层向上返回调用,得到最终解。这里递归就像我们爬山,一个台阶一个台阶爬到山顶后,最终还是要一个台阶一个台阶下山的道理一样。

时间: 2024-11-10 06:02:20

J2SE快速进阶——递归算法的相关文章

J2SE快速进阶——IO流的四个基本抽象类InputStream、OutputStream、Reader、Writer

上文中对java.io包中的四个抽象类及其关系简单了解了一下,这里进一步对它们及其子类进一步总结一下. 在上篇博客末尾,贴出了Java中的整个IO家族,之后小编又重修改了一下,在之前的基础上,标识出了节点流与处理流(绿色为节点流,黄色为处理流). 这里我们分别来说一下这四个抽象类. 细心的你也许会发现,大部分输入流和输出流都是成对的,有输入就有输出,一一对应. InputStream 输入字节流InputStream的作用是标志那些从不同数据起源产生输入的类. 基本方法有: int read()

J2SE快速进阶——向上转型及其内存分析

还记得刚通过C#学习面向对象时,接触了对象转型,最近学习Java,又遇到了.这里再用Java分析一下对象的转型,并适当利用内存分析来加深理解. 向上转型 我们都知道,狗是动物中的一种,那么如果现在有一个Dog类和Animal类,那么他们的关系就是Dog类继承Animal类. 我们经常说,狗是动物,实际上"狗是动物"这句话就是向上转型的一个例子,即把狗(子类)当做动物(父类)来看待.用一句话来总结,向上转型就是父类的引用指向子类的实例. 实例说明&&内存分析 下面就用一个

J2SE快速进阶——Java内存分析

程序的执行过程 要在Java中分析内存,我们先来了解一下程序的执行过程: 正如上图所示,大致分为3个步骤: 1.最开始,我们的程序是存在于硬盘中的,当启动运行时,程序会被加载(load)到内存中去,这里的内存可以看做我们的内存条: 2.此时,内存中除了存在刚加载的程序的代码,还存在操作系统本身的代码(好吧,此句可以当做废话→_→),操作系统会找到程序中的Main方法开始执行程序: 3.第三步就是本文的重点,系统在程序执行过程中对内存的管理.在Java中,内存大致会被分为四块--heap(栈).s

J2SE快速进阶——IO流

IO流的概念 IO流是从数据从一处流向另一处的抽象,就像水流从管道的一端流向另一端一样.在程序中,所有的数据都是以流的方式来传输和保存的. JDK所提供的所有流类位于java.io包中,并且这些类都分别继承自以下四种抽象流类:InputStream.OutputStream.Reader和Writer. 说明: InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位). OutputStream:继承自OutputStream的流都是程序用于

J2SE快速进阶——数组(及其内存分析 )

早在学习其他语言如C.VB.C#.C++等时也学习过数组,平时项目中也经常用,但从没仔细再深入了解,这里学习Java又遇到了,重新整理一下. 一句话概括数组是什么:数组就是有一组相同数据类型的数据的集合. 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量.数组中每个元素的类型可以是任何数据类型. 数组定义和初始化 数组的声明可以看做是在内存中为数组的每个元素分配空间的过程:数组的初始化可以看做往分配的空间里赋值的过程. 数组的定义 Java中定义数组的格式为:类

J2SE快速进阶——Socket编程入门(TCP/UDP)

作品展时,我们的作品 "超级飞聊" 的主打功能就是聊天,包括局域网聊天.外网聊天等,虽然那时是用VB实现的(winsock控件),不过每种编程中的思想还是大同小异的,所以学习Java中的Socket编程时,倍感亲切啊. 概念了解 Socket又称"套接字",用来向网络中的主机发出请求或者应答网络中发出的请求. 文章开头先来简单了解一下TCP与UDP这两个协议: TCP TCP(Transmission Control Protocol传输控制协议)是一种面向连接的.

J2SE快速进阶——Java中的equals和==的区别

我们都知道,Java中数据类型大体上可分为两类:基本数据类型和引用数据类型.equals和==都是用来比较数据与数据是否"相等". 基本数据类型的比较 基本数据类型之间的比较用"==",用来判断它们的值是否相等. 示例代码: public class Test{ public static void main(String[] args){ int i1=9; int i2=9; boolean b1=true; boolean b2=true; char c1='

J2SE快速进阶——多线程之synchronized

我和老婆去银行取钱 有一天,和老婆打了个赌,现在我的银行账号里共有5000块钱,我们去银行同时取钱,看我俩能不能同时取出5000来....(PS:打赌的代价是:如果都能取出5000,那这10000块都给她买吃的!如果只能取5000,嘿嘿,那就只用着5000块给她买吃的~~~~怎么觉得这条件有点怪怪的nie?) 心动不如行动!她拿着存折去柜台取,我拿着银行卡去ATM机取,找了个合适的时机,我在输入好金额时,一直盯着那个teller的手,他在一切准备就绪后敲回车的同时,我以迅雷不及掩耳之势按下了确定

J2SE快速进阶——Java多线程机制

学习Java中的线程时,自然而然地联想到之前学过的操作系统中处理器那一块的知识. 定义 文章开头,先大概说一下程序.进程和线程的概念及其之间的关系. 程序:程序就是一段静态的代码,或者一个可执行程序. 进程:进程是程序的一次动态执行的过程,它对应着从代码加载.运行到结束的一次动态的执行过程. 线程:比进程更小的执行单位,一个进程在执行过程中,可以产生多个线程,也就是多个分支.它是程序执行流的最小单位. 来看一个小程序: public class Test { public static void