Java过程——嵌套与迭代

迭代与嵌套是面向过程的两个非常有用的算法,在一些java开发中也应用的比较多。今天学习了一些皮毛,将其总结如下。

1线型的递归和迭代:

线型过程结构比较简单,比较容易理解,并且从描述到代码的书写比较容易实现。最常见的是计算阶乘:

1.1、用迭代的想法是,从1开始计算,每次乘上新的i,新计算的结果代替旧的结果:n->n*i;

int n=1;
for(int i=1;i<n;i++){
n=n*i;
}

1.2、用嵌套的想法是,f(n)=nf(n-1),当n等于1时返回1;于是

private static int factorial(int n){
if(n==1)
return 1;
else
return n*factorial(n-1);
}

1.3、迭代的过程比较简单,不想多说,在写程序时,可以写成迭代的尽量使用迭代,嵌套相对而言更消耗计算资源。

这里要简单的说一下迭代的整个计算过程。编写嵌套算法,最重要有两点:程序的出口和程序过程。例如

程序的出口是指,程序最末端程序应该返回的值,例如在1.2中的if(n==1) return 1;就是程序的末端。

有了程序的末端,就要去设计程序的过程,嵌套的过程并不容易书写,很容犯错。比如有这样两个方法,很类似,得出的结果相差却很大:

private static void show1(int i) {
        // TODO 自动生成的方法存根
        if (i < 6)
            t(i + 1);
        else
            System.out.print(i + " ");
    }
private static void show2(int i) {
        // TODO 自动生成的方法存根
        if (i < 6)
            t(i + 1)        
       System.out.print(i + " ");
    }

同样给i初值是1时,show1打印的是6,show2打印的 是6 5 4 3 2 1。

分析一下这两个程序,show1(1),返回show1(2)。。。最后,当show1(6)时,程序结束,打印6。而show2(1)就不一样了,show2(1)的出口也是6,但是,在执行show1(1)时,程序有一部分(system.out.print(…))没有执行,因为程序进入了下一个嵌套show2(2),称没有执行的语句被暂时挂起。这样每个循环都被挂起一段代码,直到show2(6)时,程序找到出口,开始往回执行嵌套过程。先打印6 之后5 再4 。。。注意打印不是先1 再2 再3 。。。

由此也可见,在嵌套中出口对于程序是很重要的。

嵌套的计算机算法可以理解为,先挂起执行代码直到找到出口,从出口开始执行代码。

还有一个经典的例子是求最大公约数的问题,这里就不多说过程了,将前人的算法留下。数学过程是,(a,b)的最大公约数,与(b,a%b)的最大公约数相等,算法因欧几里德而出名,命名为欧几里德辗转算法。代码这里就不在给出了

当然线型过程都是可以优化的,在这里就不多说了。

如果说线型结构相对而言简单一下,树形结构要复杂很多,也更管用,可以解决许多日常世纪问题。

2、树形递归

树形算法要复杂很多,并且使用嵌套的方式更容易理解。

一个简单的例子是斐波数:

最常用的数学描述f(n)=f(n-1)+f(n-2)。n=2时 1,n=1时 1。

使用迭代或者是递归的方法都很容易实现,这里就不在写详细的实现过程了。简单的把嵌套的树形图画一下:

树形过程还是挺复杂的,上面只是一个最简单的例子,下面举一个很有意思的例子说明一下嵌套在解决复杂问题中比迭代更容易解决问题的例子:

有1个美国人,他有一枚祖传的1美元(100美分)硬币。有一天,他找到正在杂货店的我,对我我“嗨,哥们,你那有零钱吗”,“当然有”我回答道,“你要哪种,我这有50美分、25美分的、10美分的、5美分的和1美分的。”“这么多啊”他诧异道,“我想把1美分换成零钱,你能告诉我一共多少中不同的方式吗?”

当然对于这个刁难我的问题,我是不会回答他的,我立马叫来隔壁正在忙着破解美国军方网络的jack,“Hi,jack,help me”我大声叫道,jack却在忙着他手头的活,沉静了半分种,他晃了晃脑袋,说了句“I know what you want to say,wait me one miniter”,果然,不到一分钟,jack说了个数字292。当我还在雾里时,那位害我死了不少脑细胞的美国人大叫道:“不可思议,你是怎么做到的,我整整算了一周才把所有的情况排序出来”。聪明的你想到解决方案了吗。

使用递归到并不是很难实现,稍微动些脑筋。

数学描述是这样的:假设Fk(n)表述n美分兑换成k枚金币的所有结果,那么Fk(n)可以递归的看成,没有其中一种硬币的结果,和除去一个其中一种硬币的剩下钱的兑换结果,写成:Fk(n)=Fk-1(n)+Fk(n-a).

比如上面的例子可以描述成,最终结果是由(100美分去除一个50美分)剩余的50美分兑换成5种硬币的全部方法加上100美分兑换成4种硬币的方法(没有50美分的这种硬币)。图形可以更好的说明这一过程,聪明的你可以在纸上做一做图形。

但是,我想提醒的是,想把这一数学过程写成计算机代码并不是一件容易的事情,这里我先不给出Java语言的代码,你可以写出来,我们一下讨论一下。

当然这里有一个挑战留给大家,包括我自己,就是怎样把这个过程写成其他的方式,大家都知道,递归法是很消耗资源的,如果你设计出了更好的算法,请与我分享,[email protected]

谢谢!

时间: 2024-10-25 05:05:25

Java过程——嵌套与迭代的相关文章

《Java设计模式》之迭代模式

迭代子模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象(internal representation). 聚集和JAVA聚集 多个对象聚在一起形成的总体称之为聚集(Aggregate),聚集对象是能够包容一组对象的容器对象.聚集依赖于聚集结构的抽象化,具有复杂化和多样性.数组就是最基本的聚集,也是其他的JAVA聚集对象的设计基础. JAVA聚集对象是实现了共同的java.util.Collection接口的对象,是JAVA语言

java进阶--嵌套类和接口

public class third { private int id1;//私有成员 public int id2; public static class class_top{ void sayid(third th){//静态嵌套类想要访问顶层类的私有/公有成员只能通过传递引用对象 th.id1=12; th.id2=12; } } public static class static_class extends class_top{ static void say_id(third th

多层嵌套可迭代列表的剥皮函数

python中很多时候可能会遇到多层嵌套可迭代列表如下: list1 = [11, 22, [33, 44, [55, 66]]] list2 = [11, 22, [33, 44]] 其中我们想要的结果只是一个所有的结果列表而已.此时就需要一个剥皮函数,把嵌套的元素全部剥离出来,放入一个列表中(递归实现).实现函数如下: def f(x, ret=None): # 把上一次的结果传递过来 if not ret: ret = [] for i in x: if isinstance(i, lis

JAVA集合元素的迭代删除

在Java中有时候我们会需要对List里面的符合某种业务的数据进行删除,但是如果不了解里面的机制就容易掉入"陷阱"导致遗漏或者程序异常.下面发表一下我自己的经验: 1.采用索引下标遍历的方式 import java.util.ArrayList; public class TestList { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer

Java多层嵌套异常处理的基本流程

异常是程序中的一些错误,但并不是所有的错误都是异常,错误有时候是可以避免的.异常的对象有两个来源,一是Java运行时环境自动抛出系统生成的异常,而不管你是否愿意捕获和处理,它总要被抛出!比如除数为0的异常.二是程序员自己抛出的异常,这个异常可以是程序员自己定义的,也可以是Java语言中定义的,用throw 关键字抛出异常,这种异常常用来向调用者汇报异常的一些信息. 异常是针对方法来说的,抛出.声明抛出.捕获和处理异常都是在方法中进行的. Java异常处理通过5个关键字try.catch.thro

【Java基础】List迭代并修改时出现的ConcurrentModificationException问题

现在有一个需求,要遍历一个List,假设List里面存储的是String对象,然后该需求事判断里面如果有某个对象,则添加一个新的对象进去.自然,我们得出下面的代码: import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Created by lili on 15/11/13. */ public class Test { public static void main(String[

储存过程嵌套临时表同名引发的BUG?

临时表使用:存储过程嵌套时,均创建了相同名称的临时表. create procedure SP_A ( @i int output )asbegin create table #t ( ta int ); insert into #t ( ta ) values ( convert(int, getdate()) ); select @i=count(0) from #t; print @i; end;gocreate procedure SP_Basbegin create table #t

for的嵌套与迭代、穷举与 while

for嵌套 //for循环的嵌套 //打印矩阵 //for (int k = 1; k <= 5; k++) //{ // for (int i = 1; i <= 5; i++) // { // Console.Write("■"); // } // Console.WriteLine(); //} //打印左下角是直角的三角形 //for (int i = 1; i <= 5; i++) //{ // for (int j = 1; j <= i; j++)

Java中递归和迭代的区别

关于递归和迭代的博客一篇: http://blog.csdn.net/believejava/article/details/8423888 递归占用的资源较多,而且容易发生内存溢出,不易管理,推荐使用迭代 包的好处是:将有相似功能java文件放在同一个包下,易于使用管理 防止命名冲突 为protected类型的变量提供保护,使其对包外不暴露,只能在包内使用. .有一个问题是为啥主函数所在的java文件不能写包名,只能import包,否则老是报错.. 还有就是我现在为啥都不需要在配置classp