自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如果要用Java實現(xiàn)算法,一定慎用遞歸

開發(fā) 后端 算法
遞歸是我們很經(jīng)典的一種算法實現(xiàn),可以很好的描述一個算法的原理!對于算法的描述、表現(xiàn)和代碼結(jié)構(gòu)理解上,遞歸都是不錯的選擇!

現(xiàn)象 :

遞歸是我們很經(jīng)典的一種算法實現(xiàn),可以很好的描述一個算法的原理!對于算法的描述、表現(xiàn)和代碼結(jié)構(gòu)理解上,遞歸都是不錯的選擇!

但是本文想說的是java實現(xiàn)一個遞歸算法的時候盡量不要用遞歸實現(xiàn),而是轉(zhuǎn)換成的非遞歸實現(xiàn)。

最近在實現(xiàn)一個比較復(fù)雜算法的時候,嘗試了一下,非遞歸實現(xiàn)相比遞歸實現(xiàn)速度上能提升1/3。

以下面一個簡單的例子來說:(注:為了描述簡單,所以這里只用一個簡單的例子)

輸入?yún)?shù):N

輸出結(jié)果: log1+log2+log3+....+logN

兩種實現(xiàn)代碼如下:

Java代碼

  1. package test;     
  2.     
  3. public class RecursiveTest {     
  4.     /**    
  5.      * 遞歸實現(xiàn)    
  6.      *     
  7.      * @param n    
  8.      * @return    
  9.      */    
  10.     public static double recursive(long n) {     
  11.         if (n == 1) {     
  12.             return Math.log(1);     
  13.         } else {     
  14.             return Math.log(n) + recursive(n - 1);     
  15.         }     
  16.     }     
  17.     
  18.     /**    
  19.      * 非遞歸實現(xiàn)    
  20.      *     
  21.      * @param n    
  22.      * @return    
  23.      */    
  24.     public static double directly(long n) {     
  25.         double result = 0;     
  26.         for (int i = 1; i <= n; i++) {     
  27.             result += Math.log(i);     
  28.         }     
  29.         return result;     
  30.     }     
  31.     
  32.     public static void main(String[] args) {     
  33.         int i = 5000000;     
  34.         long test = System.nanoTime();     
  35.         long start1 = System.nanoTime();     
  36.         double r1 = recursive(i);     
  37.         long end1 = System.nanoTime();     
  38.         long start2 = System.nanoTime();     
  39.         double r2 = directly(i);     
  40.         long end2 = System.nanoTime();     
  41.     
  42.         System.out.println("recursive result:" + r1);     
  43.         System.out.println("recursive time used:" + (end1 - start1));     
  44.         System.out.println("non-recursive result:" + r2);     
  45.         System.out.println("non-recursive time used:" + (end2 - start2));     
  46.     }     
  47. }    

 

得到運行結(jié)果如下:

 

  1. recursive result:7.212475098340103E7  
  2. recursive time used:539457109   
  3. non-recursive result:7.212475098340103E7  
  4. non-recursive time used:282479757  

 

可以看出遞歸的運行時間是非遞歸運行時間將近2倍。

(注:以上代碼還是在-Xss200m的參數(shù)下運行的,如果??臻g不足,直接不能運行)

原因簡單分析:

 

 

上圖是java線程棧的結(jié)構(gòu)。java將為每個線程維護(hù)一個堆棧,堆棧里將為每個方法保存一個棧幀,棧幀代表了一個方法的運行狀態(tài)。 也就是我們常說的方法棧。***一個為當(dāng)前運行的棧幀。

那么每一次方法調(diào)用會涉及:

1.為新調(diào)用方法的生成一個棧幀

2.保存當(dāng)前方法的棧幀狀態(tài)

3.棧幀上下文切換,切換到***的方法棧幀。

遞歸實現(xiàn)將導(dǎo)致在棧內(nèi)存的消耗(往往需要調(diào)整Xss參數(shù))和因為創(chuàng)建棧幀和切換的性能開銷,最終大大的影響效率!

所以,如果你想提升你的算法效率,不要使用遞歸實現(xiàn)是一個基礎(chǔ)原則!

另外,遞歸是我們用來理解算法的一個方法,當(dāng)用代碼來實現(xiàn)的時候基本都可以轉(zhuǎn)換成非遞歸的代碼實現(xiàn)!

【編輯推薦】

  1. JavaOne 2009第三天:微軟與Sun/Oracle攜手并進(jìn)
  2. 開發(fā)高可移植性J2ME的軟件
  3. Java虛擬機(jī)(JVM)中的內(nèi)存設(shè)置詳解
  4. Java中的堆內(nèi)存與棧內(nèi)存分配淺析
  5. 非常全面的實用JavaScript開發(fā)工具列表
責(zé)任編輯:金賀 來源: ITEYE博客
相關(guān)推薦

2022-08-31 22:50:13

JavaScript函數(shù)JSON

2020-08-30 14:31:40

Python編程語言開發(fā)

2021-01-14 10:38:41

Java枚舉工具

2015-03-30 10:48:17

大數(shù)據(jù)大數(shù)據(jù)處理Hadoop

2021-02-26 09:04:22

數(shù)組ArrayListHashMap

2013-09-03 09:09:30

大數(shù)據(jù)

2017-09-28 08:35:35

前端HTML標(biāo)簽大全

2019-01-21 08:20:17

通信4G5G

2015-06-17 11:18:01

WiFi

2018-08-24 09:02:26

2022-02-18 12:24:39

PythonNumpy Arra大數(shù)據(jù)

2016-09-21 22:12:43

網(wǎng)絡(luò)爬蟲Java開源

2022-08-01 07:07:41

TCP協(xié)議后端

2022-08-26 08:17:32

Webshiro關(guān)系

2019-11-12 08:53:00

線上命令日志

2021-01-19 11:00:14

CPU核心單核

2017-01-19 17:57:47

大數(shù)據(jù)

2021-06-01 20:38:04

Vuex對象import

2015-03-17 15:18:02

私有云公共云數(shù)據(jù)中心

2022-11-16 11:55:22

網(wǎng)絡(luò)連接命令
點贊
收藏

51CTO技術(shù)棧公眾號