亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

java語言

Java中的迭代和遞歸講解

時間:2024-08-07 16:26:40 java語言 我要投稿
  • 相關(guān)推薦

Java中的迭代和遞歸講解

  迭代使用的是循環(huán)(for,while,do...wile)或者迭代器,當(dāng)循環(huán)條件不滿足時退出。而遞歸,一般是函數(shù)遞歸,可以是自身調(diào)用自身,也可以是非直接調(diào)用,即方法A調(diào)用方法B,而方法B反過來調(diào)用方法A,遞歸退出的條件為if,else語句,當(dāng)條件符合基的時候退出。下面是小編為大家整理的Java中的迭代和遞歸講解,歡迎參考~

  前言

  迭代使用的是循環(huán)(for,while,do...wile)或者迭代器,當(dāng)循環(huán)條件不滿足時退出。而遞歸,一般是函數(shù)遞歸,可以是自身調(diào)用自身,也可以是非直接調(diào)用,即方法A調(diào)用方法B,而方法B反過來調(diào)用方法A,遞歸退出的條件為if,else語句,當(dāng)條件符合基的時候退出。

  上面是迭代和遞歸的語法特性,他們在Java中有什么不同呢?

  一、遞歸

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

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

  代碼一

  int factorial (int n) {

  if (n == 1) {

  return 1;

  } else {

  return n*factorial(n-1);

  }

  }

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

  二、迭代

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

  代碼二

  int factorial (int n) {

  int product = 1;

  for(int i=2; i<n; i++) {

  product *= i;

  }

  return product;

  }

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

  三、迭代 VS 遞歸

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

 。ㄗⅲ涸闹嘘P(guān)于其區(qū)別寫的有點扯,這里就不翻譯了,下面是筆者自己總結(jié)內(nèi)容。)

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

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

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

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

  四、數(shù)形遞歸

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

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

  遞歸實現(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);

  }

  }

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

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

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

  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;

  }

  雖然使用遞歸的方式會有冗余計算,可以用迭代來代替。但是這并不表明遞歸可以完全被取代。因為遞歸有更好的可讀性。

【Java中的迭代和遞歸講解】相關(guān)文章:

Java中的main()方法的使用講解10-31

java講解06-23

講解Java的Spring框架中的AOP實現(xiàn)10-30

Java中final關(guān)鍵字用法的講解10-13

舉例講解Java中的多線程范文欣賞06-16

講解Java編程中finally語句的使用方法08-11

講解Java的泛型07-13

java ClassLoader機(jī)制講解07-31

如何實現(xiàn)java漢諾塔遞歸算法09-20

講解Java中如何構(gòu)造內(nèi)部類對象及訪問對象07-24