递归算法经典实例java,java递归简单案例
00-1010 Java中方法的使用。方法的定义和使用是什么?如何调用方法以及方法调用过程的形参和实参?方法重载方法签名递归
目录
00-1010日常生活中举个例子。比如我们学校班长发消息。比如他想让班里所有人都去参加某教学楼一个班的会议,他就给所有人发消息。同学们,今天我们有一个重要的会议要开。请来某教学楼的一个班。如果班长要给每个人发信息,一个班会有很多人发信息会很累。改变主意,班长群发消息。也就是类似于java中的方法,我们定义一个方法来实现你需要的功能,你想调用就可以随意调用。
如果一个函数在编程中被重复实现,它将
1.使程序变得繁琐
2.开发效率低,做了大量重复性工作。
3.不利于维护。当需要更改时,所有使用该代码的位置都需要修改。
4.不利于重用。
方法的含义:
1.它是一个可以模块化的组织代码(当代码规模复杂时)。
2.代码可以重用,一个代码可以用在多个地方。
3.让代码更容易理解。
4.调用现有方法直接开发,不需要重复造轮子。
00-1010定义规范:
修饰符返回值类型方法名([参数类型参数.]){方法体代码;【返回返回值】;}
我们举个例子:判断是不是闰年:
public static boolean is leapy year(int year){ if(year%4==0year0!=0year@0==0) {返回true}返回false}实现两个数的相加:
公共静态int add (int x,int y){//实现两个数的相加返回x y;}这个方法可以在需要这个函数的时候调用,所以不需要重新编写,减少了代码的冗余。
一些方法的注意事项:
1.修饰词:现阶段直接用public static进行固定搭配。
2.返回值类型:如果方法有返回值,返回值类型必须与返回的实体类型一致;如果没有返回值,就必须写成void。
3.方法名称:以小驼峰命名。
4.参数列表:如果方法没有参数,将不在()中写入任何内容。如果有参数,要指定参数类型,多个参数之间用逗号隔开。
5.方法体:要在方法内部执行的语句。
6.在java中,方法必须写在类中。
7.在java中,方法不能与定义嵌套。
8.在java中,没有办法声明它
00-1010举个例子:或者上面的例子来判断闰年?
public static boolean is leapy year(int year){ if(year%4==0year0!=0year@0==0) {返回true}返回false} public static void main(String[]args){ Scanner scan=new Scanner(system . in);System.out.println(请输入年份确定是否是闰年?);int year=scan . nextint();If(isLeapYear(year)) {//是闰年System.out.print(year 是闰年);} else {System.out.print(年份不是闰年);}}我们来剖析一下这段代码:
首先我们需要定义一年:
调用方法:
我们可以总结出该方法的调用过程大致如下:
调用方法-传递参数-
gt;找到方法地址--->执行被调方法的方法体--->被调方法结束返回--->回到主调方法继续往下执行
注意事项:
只有定义完方法之后才可以调用方法。并且只有调用方法时,方法才会执行。
我们定义的方法可以多次重复调用。完成我们想要完成的需求。
举个实例:计算1!+2!+3!+4!+5!;
这个代码虽然简单但是可以证明我们把一个功能都实现成一个方法,这样我们调用起来,代码逻辑就很清晰,所以建议我们实现一个功能的时候都要把它封装成一个方法。
方法的形参和实参
Java中方法的形参就相当于sum函数中的自变量n,用来接收sum函数在调用时传递的值的。形参的名字可以随意取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值。
例如:实现一个方法交换两个整型变量
传值调用:
根据上面的答案,并不是我们想要的结果那是为什么呢?
我们来剖析一下:
有的人还会说那我把形参写成 a和b他会交换a和b的值么?
答案并不会,形参的名字可以任意取与名字无关,如果写成a和b那只能说明原来的两人和你形参这两个人是重名的,并不会本质的改变。
那我们究竟怎么才能改变两个数的值呢?
这就与c语言类似,在c语言中是传两个数的地址而在java中传的是引用,引用存储的是这两个变量在内存的地址,通过地址就可以改变。
由于java语言中没有所谓的取地址,在Java中有引用类型,引用类型所引用的变量就是存储在内存当中的地址。通过地址就可以实质的改变某个值。
在java中引用类型有许多比如,类,对象,数组,字符串等等。
我们接下来利用数组进行交换两个数的值。
public static void Swap(int[] array) { int tmp = array[0]; array[0] = array[1]; array[1] = tmp; }public static void main(String[] args) { int[] array =new int[]{10,20}; Swap(array); System.out.println(Arrays.toString(array));}
为啥两个值交换呢?因为数组是引用类型,引用变量(这里是array)存放的是数组中的元素在内存中的地址,通过地址就可以真正的改变这两个值。
方法重载
百度百科:方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。调用重载方法时,Java编译器能通过检查调用的方法的参数类型和个数选择一个恰当的方法。方法重载通常用于创建完成一组任务相似但参数的类型或参数的个数或参数的顺序不同的方法。Java的方法重载,就是在类中可以创建多个方法,它们可以有相同的名字,但必须具有不同的参数,即或者是参数的个数不同,或者是参数的类型不同。调用方法时通过传递给它们的不同个数和类型的参数,以及传入参数的顺序来决定具体使用哪个方法。
看上面复杂的概念一时可能看不懂不如我来举一个例子吧。
好比如我们要实现数的加法,要同时实现两个整形的加法,两个浮点数的加法,三个整形数的加法
我们没学过方法重载可能会这么写。
public static int addTwoInt(int a,int b) { return a+b; } public static int addThirdInt(int a,int b,int c) { return a+b+c; } public static double addTwoDouble(double a,double b) { return a+b; } public static void main(String[] args) { int a =10; int b =20; int c =20; double d =3.14; double e =9.89; System.out.println(addTwoInt(a, b)); System.out.println(addThirdInt(a, b, c)); System.out.println(addTwoDouble(d, e)); }
对于学过方法重载的同学看见这个代码真想。。。。。
这样的代码是不是看着很繁琐,每一次实现一个加法就要起一个名。上面的代码需要提供许多不同的方法名,而取名字本来就是让人头疼的事情
那我们接下来使用方法重载又有多大的变化呢?
我们都使用相同的名字在idea不会报错,原因是在java语言中支持方法的重载。
所以,在Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了
根据这三个代码我们就可以总结出方法重载的规则了
第一:方法名相同;
第二:返回值不做要求;
第三:方法名的参数列表不同(包括参数的返回类型,形参的顺序,形参的个数);
方法签名
既然有方法重载,那java是内部是怎么支持重载的呢?那就要说一说方法签名了。
方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。
我们通过找到生成代码的.class文件 然后右键打开powershell
输入一个 javap -v +文件名
回车之后就可以看到java代码的汇编代码,根据汇编代码就可以看到方法的签名。
我们既然定义了相同名字的方法,那编译器是怎么识别我们要调用哪个方法呢?没错这就是方法签名起了作用,每定义一个方法在编译完生成class文件,就会生成一个方法签名,编译器就是根据每个方法的签名不同而识别的,比如你要计算两个double类型的和,那他就会直接找DD的这个签名而不会匹配到其他的签名。
递归
递归定义是数理逻辑和计算机科学用到的一种定义方式,使用被定义对象的自身来为其下定义(简单说就是自我复制的定义)。递归定义(recursive definition)亦称归纳定义,一种实质定义,指用递归的方法给一个概念下的定义
通俗的讲,当我们遇到一个问题,这个问题具有每一步的解法都是相同的,我们就可以将这个大问题分解成多个子问题,最终这个问题就会被解决;
实现递归有两个必要条件:
第一:子问题必须要与原问题的解决方法是相同的。
第二:必须要有判断条件防止递归深度太深导致栈溢出。
我们来举一个经典递归例子:求N的阶乘
我们可以思考一下根据上图的推理第一:他符合原问题的解法与子问题的解法是一致的,有符合判断条件(判断条件就是如果n==1的时候1!=1).这就是递归 从5!被分解成5*4!,4*3!.......
这样的问题就迎刃而解了。
public static int factor(int n) { if(n==1) { return 1; } return n* factor(n-1); } public static void main(String[] args) { System.out.println(factor(5)); }
递归小练习
按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)。
这个题我们怎么思考呢?
首先要得到一个数字的每一位肯定是除10 和模10循环知道数字为0
那我们可以将1234这样来分解;
public static void printEveryNum(int num) { if(num<=9) { System.out.print(num+" "); return; } printEveryNum(num/10); System.out.print(num%10+" "); } public static void main(String[] args) { int num =1234; printEveryNum(num); }
递归求 1 + 2 + 3 + ... + 10 递归实现1一直加到10的和
public static int sum(int num) { if(num==0) { return 0; } return num+sum(num-1); } public static void main(String[] args) { int a =10; System.out.println(sum(100)); }
到此这篇关于全面分析Java方法的使用与递归的文章就介绍到这了,更多相关Java方法与递归内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。