1. 程式人生 > >Java中遞歸和循環的優劣

Java中遞歸和循環的優劣

static all 清晰 package 使用 出現 png 部分 過程

介紹:
  你用你手中的鑰匙打開一扇門,結果去發現前方還有一扇門,緊接著你又用鑰匙打開了這扇門,然後你又看到一扇門......但是當你開到一扇門時,發現前方是一堵墻無路可走了,你選擇原路返回--這就是遞歸。
  但是如果你打開一扇門後,同樣發現前方也有一扇門,緊接著你又打開下一扇門.....但是卻一直沒有碰到盡頭--這就是循環。
  簡單來說:循環是有去無回,而遞歸是有去有回(因為存在終止條件)。
  循環:當滿足某一條件時反復執行某一操作(循環體)。
  遞歸:在一個方法內部對自身進行調用的方法。
遞歸結構包括兩個部分:
  1、遞歸頭:即什麽時候不調用自身方法,也就是遞歸的結束條件。如果沒有遞歸頭,程序將陷入死循環。

  2、遞歸體:即什麽時候需要調用自身方法。
好了,廢話不多說,直接來擼代碼(計算階乘的方法)。

package com.bjwyj.method;
/**
 * 遞歸和循環的比較
 * @author 吳永吉
 *
 */
public class TestRecursion {
	public static void main(String[] args) {
		//以下調用System下的currentTimeMillis()方法只是為了說明遞歸調用比循環調用更耗時
		long l1 = System.currentTimeMillis();	
		System.out.println(factorial(5));
		long l2 = System.currentTimeMillis();
		System.out.println("遞歸計算階乘耗時:"+(l2-l1));
		
		System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
		long time1 = System.currentTimeMillis();
		System.out.println(factorialLoop(5));
		long time2 = System.currentTimeMillis();
		System.out.println("循環計算階乘耗時:"+(time2-time1));
	}
	
	//使用遞歸定義計算階乘的方法
	public static long factorial(int num) {
		if(num==1) {	//遞歸頭
			return 1;
		}else {
			return num*factorial(num-1);	//遞歸體
		}
	}
	
	//使用循環定義計算階乘的方法
	public static long factorialLoop(int n) {
		int result = 1;	//接收計算結果
		while(n>1) {
			result *= n*(n-1);	//實現計算結果的累乘操作
			n -= 2;	//每次減去2,實現數字的叠代操作
		}
		return result;
	}
}

  執行結果:

120
遞歸計算階乘耗時:1
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
120
循環計算階乘耗時:0

  

  由結果可以看出,使用遞歸算法比使用循環算法更耗時。
  為了更好地比較遞歸算法的優劣,上述采用while循環與遞歸算法進行對比。
  先來分析上述遞歸方法的執行過程,如下圖:

技術分享圖片

  循環方法的執行過程,如下圖:

技術分享圖片

  這裏為了看起來清晰,只是簡單地畫出了棧內存中的執行過程(這樣畫更便於理解)。

總結:
  棧,主要是用來存放棧幀的,每執行一個方法就會出現壓棧操作,所以采用遞歸的時候產生的棧幀比較多,遞歸就會影響到內存,非常消耗內存。而使用循環就執行了一個方法,壓入棧幀一次,只存在一個棧幀,所以比較節省內存。



Java中遞歸和循環的優劣