遞迴和迭代的本質是一樣的:有限次重複相同程式碼,從初始資料應用相同邏輯不斷計算得到結果。
1.流程不一樣
舉個栗子:
初始值/遞迴出口: f(0) = 0; 邏輯: f(n) = f(n-1) + 1; 遞迴入口: f(n) & n=100 結果: f(100)
遞迴:
遞迴不算向下挖,不斷把來路資訊交給stack儲存,例如f(50)是在f(51)的body裡被call。直到遞迴 出口:
達到出口之後,又會把存在stack裡的資訊逆序逐個取出來,計算出f1. 以此類推。
遞迴透過不停呼叫自身達到重複邏輯的目的。
迭代:
拿到初始值 -> 重複邏輯 -> 結果。
迭代透過控制結構的迴圈達到重複邏輯的目的。
2. 實現效率不一樣
所有的程式碼最後對於CPU來說都是加法,只是暫存器裡面的內容是不一樣的。暫存器會有不同的level,邏輯上越接近CPU越快。 上個例子中的迭代法就很明確。s的值會被放到累計暫存器中,在計算過程中不會被其它變數代替,不需要用到記憶體,計算會很快。 然而遞迴在向下挖的過程中會不斷把相關資訊儲存到記憶體的stack中,清空暫存器,load下一輪計算資訊到暫存器。要知道暫存器要比記憶體的速度高几個數量級,時間並沒有完全用在計算上,而用在資料的轉移。 現在很多編譯器會對遞迴進行最佳化,讓其實現和迭代一樣,具體我也不懂。
遞迴最大的缺點不在於此,而在於重複計算。在上面單變數的栗子中,我們並不能看到重複計算。但是如果遞迴公式改成多變數
那麼在實現過程中就會重複計算。 例如f(n-1, m-1)會被計算兩次,而且下面的也會繼續被重複計算。也可以用global var去記錄f(n, m)是否已經被計算。圖演算法裡面的搜尋可以用二維陣列記錄這個點是否被訪問過。
3. 程式碼實現難度不一樣
用遞迴寫程式碼要容易很多,它更接近人的思維過程,只需要定義好出口和邏輯。你可能會問,上面迭代的程式碼好像更清楚。如果變數增多,實現難度將增加,一般都是多層迴圈,需要開闢陣列儲存結果。如果是遞迴,這些都有編譯器完成。
有錯誤的話請指正:) Mr.Black
遞迴和迭代的本質是一樣的:有限次重複相同程式碼,從初始資料應用相同邏輯不斷計算得到結果。
1.流程不一樣
舉個栗子:
初始值/遞迴出口: f(0) = 0; 邏輯: f(n) = f(n-1) + 1; 遞迴入口: f(n) & n=100 結果: f(100)
遞迴:
遞迴不算向下挖,不斷把來路資訊交給stack儲存,例如f(50)是在f(51)的body裡被call。直到遞迴 出口:
達到出口之後,又會把存在stack裡的資訊逆序逐個取出來,計算出f1. 以此類推。
遞迴透過不停呼叫自身達到重複邏輯的目的。
迭代:
拿到初始值 -> 重複邏輯 -> 結果。
迭代透過控制結構的迴圈達到重複邏輯的目的。
2. 實現效率不一樣
所有的程式碼最後對於CPU來說都是加法,只是暫存器裡面的內容是不一樣的。暫存器會有不同的level,邏輯上越接近CPU越快。 上個例子中的迭代法就很明確。s的值會被放到累計暫存器中,在計算過程中不會被其它變數代替,不需要用到記憶體,計算會很快。 然而遞迴在向下挖的過程中會不斷把相關資訊儲存到記憶體的stack中,清空暫存器,load下一輪計算資訊到暫存器。要知道暫存器要比記憶體的速度高几個數量級,時間並沒有完全用在計算上,而用在資料的轉移。 現在很多編譯器會對遞迴進行最佳化,讓其實現和迭代一樣,具體我也不懂。
遞迴最大的缺點不在於此,而在於重複計算。在上面單變數的栗子中,我們並不能看到重複計算。但是如果遞迴公式改成多變數
那麼在實現過程中就會重複計算。 例如f(n-1, m-1)會被計算兩次,而且下面的也會繼續被重複計算。也可以用global var去記錄f(n, m)是否已經被計算。圖演算法裡面的搜尋可以用二維陣列記錄這個點是否被訪問過。
3. 程式碼實現難度不一樣
用遞迴寫程式碼要容易很多,它更接近人的思維過程,只需要定義好出口和邏輯。你可能會問,上面迭代的程式碼好像更清楚。如果變數增多,實現難度將增加,一般都是多層迴圈,需要開闢陣列儲存結果。如果是遞迴,這些都有編譯器完成。
有錯誤的話請指正:) Mr.Black