最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的迭代和遞歸詳解

 更新時(shí)間:2016年11月23日 10:16:48   投稿:daisy  
這篇文章主要給大家介紹了關(guān)于Java中的迭代和遞歸,文章顯示分別介紹了Java中的迭代和遞歸,而后又介紹了迭代和遞歸的區(qū)別以及數(shù)形遞歸的相關(guān)內(nèi)容,文中介紹的很詳細(xì),相信會(huì)對(duì)大家學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友們可以參考借鑒。

前言

最近在看書的時(shí)候看到這一內(nèi)容,感覺還是蠻有收獲的。迭代使用的是循環(huán)(for,while,do...wile)或者迭代器,當(dāng)循環(huán)條件不滿足時(shí)退出。而遞歸,一般是函數(shù)遞歸,可以是自身調(diào)用自身,也可以是非直接調(diào)用,即方法A調(diào)用方法B,而方法B反過來調(diào)用方法A,遞歸退出的條件為if,else語句,當(dāng)條件符合基的時(shí)候退出。

上面是迭代和遞歸的語法特性,他們?cè)贘ava中有什么不同呢?下面通過這篇文章來詳細(xì)了解了解。

一、遞歸

提到迭代,不得不提一個(gè)數(shù)學(xué)表達(dá)式: n!=n*(n-1)*(n-2)*...*1

有很多方法來計(jì)算階乘。有一定數(shù)學(xué)基礎(chǔ)的人都知道n!=n*(n-1)!因此,代碼的實(shí)現(xiàn)可以直接寫成:

代碼一

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

在執(zhí)行以上代碼的時(shí)候,其實(shí)機(jī)器是要執(zhí)行一系列乘法的: factorial(n) factorial(n-1) factorial(n-2) → … → factorial(1) 。所以,需要不斷的跟蹤(跟蹤上次計(jì)算的結(jié)果)并調(diào)用乘法進(jìn)行計(jì)算(構(gòu)建一個(gè)乘法鏈)。這類不斷調(diào)用自身的運(yùn)算形式稱之為遞歸。遞歸可以進(jìn)一步的分為線性遞歸和數(shù)形遞歸。信息量隨著算法的輸入呈線性增長的遞歸稱之為線性遞歸。計(jì)算n!(階乘)就是線性遞歸。因?yàn)殡S著N的增大,計(jì)算所需的時(shí)間呈線性增長。另外一種信息量隨著輸入的增長而進(jìn)行指數(shù)增長的稱之為樹形遞歸。

二、迭代

另外一種計(jì)算n!的方式是:先計(jì)算1乘以2,然后用其結(jié)果乘以3,再用的到的結(jié)果乘以4….一直乘到N。在程序?qū)崿F(xiàn)時(shí),可以定義一個(gè)計(jì)數(shù)器,每進(jìn)行一次乘法,計(jì)數(shù)器都自增一次,直到計(jì)數(shù)器的值等于N截至。代碼如下:

代碼二

int factorial (int n) {
 int product = 1;
 for(int i=2; i<n; i++) {
  product *= i;
 }
 return product;
}

和代碼一相比,代碼二沒有構(gòu)建一個(gè)乘法鏈。在進(jìn)行每一步計(jì)算時(shí),只需要知道當(dāng)前結(jié)果(product)和i的值就可以了。這種計(jì)算形式稱之為迭代。迭代有這樣幾個(gè)條件:1、有一個(gè)有初始值的變量。2、一個(gè)說明變量值如何更新的規(guī)則。3、一個(gè)結(jié)束條件。(循環(huán)三要素:循環(huán)變量、循環(huán)體和循環(huán)終止條件)。和遞歸一樣。時(shí)間要求隨著輸入的增長呈線性的可以叫做線性迭代。

三、迭代 VS 遞歸

比較了兩個(gè)程序,我們可以發(fā)現(xiàn),他們看起來幾乎相同,特別是其數(shù)學(xué)函數(shù)方面。在計(jì)算n!的時(shí)候,他們的計(jì)算步數(shù)都是和n的值成正比的。但是,如果我們站在程序的角度,考慮他們是如何運(yùn)行的話,那么這兩個(gè)算法就有很大不同了。

(注:原文中關(guān)于其區(qū)別寫的有點(diǎn)扯,這里就不翻譯了,下面是筆者自己總結(jié)內(nèi)容。)

首先分析遞歸,其實(shí)遞歸最大的有點(diǎn)就是把一個(gè)復(fù)雜的算法分解成若干相同的可重復(fù)的步驟。所以,使用遞歸實(shí)現(xiàn)一個(gè)計(jì)算邏輯往往只需要很短的代碼就能解決,并且這樣的代碼也比較容易理解。但是,遞歸就意味著大量的函數(shù)調(diào)用。函數(shù)調(diào)用的局部狀態(tài)之所以用棧來記錄的。所以,這樣就可能浪費(fèi)大量的空間,如果遞歸太深的話還有可能導(dǎo)致堆棧溢出。

接下來分析迭代。其實(shí),遞歸都可以用迭代來代替。但是相對(duì)于遞歸的簡單易懂,迭代就比較生硬難懂了。尤其是遇到一個(gè)比較復(fù)雜的場(chǎng)景的時(shí)候。但是,代碼的難以理解帶來的有點(diǎn)也比較明顯。迭代的效率比遞歸要高,并且在空間消耗上也比較小。

      遞歸中一定有迭代,但是迭代中不一定有遞歸,大部分可以相互轉(zhuǎn)換。

      能用迭代的不要用遞歸,遞歸調(diào)用函數(shù)不僅浪費(fèi)空間,如果遞歸太深的話還容易造成堆棧的溢出。

四、數(shù)形遞歸

前面介紹過,樹遞歸隨輸入的增長的信息量呈指數(shù)級(jí)增長。比較典型的就是斐波那契數(shù)列:

用文字描述就是斐波那契數(shù)列中前兩個(gè)數(shù)字的和等于第三個(gè)數(shù)字:0,1,1,2,3,5,8,13,21……

遞歸實(shí)現(xiàn)代碼如下:

int fib (int n) {
 if (n == 0) {
  return 0;
 } else if (n == 1) {
  return 1;
 } else {
  return fib(n-1) + fib(n-2);
 }
}

計(jì)算過程中,為了計(jì)算fib(5) ,程序要先計(jì)算fib(4) fib(3) ,要想計(jì)算fib(4) ,程序同樣需要先計(jì)算 fib(3) fib(2) 。在這個(gè)過程中計(jì)算了兩次fib(3)。

從上面分析的計(jì)算過程可以得出一個(gè)結(jié)論:使用遞歸實(shí)現(xiàn)斐波那契數(shù)列存在冗余計(jì)算。

就像上面提到的,可以用遞歸的算法一般都能用迭代實(shí)現(xiàn),斐波那契數(shù)列的計(jì)算也一樣。

int fib (int n) {
 int fib = 0;
 int a = 1;
 for(int i=0; i<n; i++) {
  int temp = fib;
  fib = fib + a;
  a = temp;
 }
 return fib;
}

雖然使用遞歸的方式會(huì)有冗余計(jì)算,可以用迭代來代替。但是這并不表明遞歸可以完全被取代。因?yàn)檫f歸有更好的可讀性。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家學(xué)習(xí)或者使用Java能有所幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • 多數(shù)據(jù)源@DS和@Transactional實(shí)戰(zhàn)

    多數(shù)據(jù)源@DS和@Transactional實(shí)戰(zhàn)

    這篇文章主要介紹了多數(shù)據(jù)源@DS和@Transactional實(shí)戰(zhàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 注解@TableName,@TableField,pgsql的模式對(duì)應(yīng)方式

    注解@TableName,@TableField,pgsql的模式對(duì)應(yīng)方式

    這篇文章主要介紹了注解@TableName,@TableField,pgsql的模式對(duì)應(yīng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Mybatis緩存機(jī)制詳解與實(shí)例分析

    Mybatis緩存機(jī)制詳解與實(shí)例分析

    Mybatis的緩存分為一級(jí)緩存和二級(jí)緩存,一級(jí)緩存是SqlSession級(jí)別的而二級(jí)緩存是mapper級(jí)別的,本文詳細(xì)的介紹了Mybatis緩存機(jī)制與實(shí)例分析,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2023-11-11
  • Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧總結(jié)

    Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧總結(jié)

    這篇文章主要介紹了Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧,分別是自然序排序、反向排序、空值安全處理、多字段組合排序、并行流加速、原地排序等,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • Java注解(annotation)簡述

    Java注解(annotation)簡述

    這篇文章主要介紹了使用java的注解(用在java類的方法上的注解)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Java雜談之代碼重構(gòu)的方法多長才算長

    Java雜談之代碼重構(gòu)的方法多長才算長

    關(guān)于代碼重構(gòu)的理解:在不改變軟件系統(tǒng)/模塊所具備的功能特性的前提下,遵循/利用某種規(guī)則,使其內(nèi)部結(jié)構(gòu)趨于完善。其在軟件生命周期中的價(jià)值體現(xiàn)主要在于可維護(hù)性和可擴(kuò)展性
    2021-10-10
  • maven的三種工程pom、jar、war的區(qū)別

    maven的三種工程pom、jar、war的區(qū)別

    這篇文章主要介紹了maven的三種工程pom、jar、war的區(qū)別,詳細(xì)的介紹pom、jar、war和區(qū)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • JAVA Iterator 轉(zhuǎn)成 List 的操作

    JAVA Iterator 轉(zhuǎn)成 List 的操作

    這篇文章主要介紹了JAVA Iterator 轉(zhuǎn)成 List 的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • IntelliJ IDEA中程序包org.slf4j找不到的解決

    IntelliJ IDEA中程序包org.slf4j找不到的解決

    這篇文章主要介紹了IntelliJ IDEA中程序包org.slf4j找不到的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 詳解如何使用Jersey客戶端請(qǐng)求Spring Boot(RESTFul)服務(wù)

    詳解如何使用Jersey客戶端請(qǐng)求Spring Boot(RESTFul)服務(wù)

    本篇文章主要介紹了詳解如何使用Jersey客戶端請(qǐng)求Spring Boot(RESTFul)服務(wù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01

最新評(píng)論

武隆县| 东港市| 友谊县| 萍乡市| 航空| 澄城县| 淅川县| 开封县| 永善县| 长岛县| 鲁甸县| 石楼县| 洛南县| 金川县| 虹口区| 保靖县| 大渡口区| 赤壁市| 油尖旺区| 南岸区| 枣强县| 翼城县| 开化县| 通海县| 札达县| 镇沅| 红安县| 都兰县| 前郭尔| 乌拉特前旗| 云林县| 噶尔县| 宝丰县| 富裕县| 温泉县| 滦平县| 上饶县| 楚雄市| 筠连县| 江口县| 东乌珠穆沁旗|