2016-06-29 106 views
-1
def reverse_append(arr, n) 
    return arr if n < 0 
    reverse_append(arr, n-1) 
    arr << n 
    arr 
end 

reverse_append([],4) #=> [0, 1, 2, 3, 4] 

我似乎無法理解這種遞歸方法。它產生一個從0到n的數組。Ruby:遞歸方法

有人可以向我解釋這一點嗎?

+0

描繪遞歸函數做什麼的最好方法是爲每個迭代添加一些輸出。嘗試在方法的最後一個'arr'行的上方添加'puts arr.inspect'並運行。 –

+0

你認爲它在哪裏? – sawa

+0

請注意詢問「向我解釋」問題。廣泛開放,「向我解釋所有的代碼」問題太廣泛了,沒有顯示任何研究/努力去理解代碼。 「解釋一條特定路線」,在研究和解釋研究如何不起作用之後,其範圍更廣泛,更有可能成爲話題。我沒有投票或投票結束,因爲它是一個小代碼塊。 –

回答

7
  1. 方法reverse_append([],4)
  2. 由於4 >= 0return聲明不會被調用。
  3. 調用方法reverse_append([],3)
  4. 由於3 >= 0return語句不會被調用。
  5. 方法reverse_append([],2)被調用。
  6. 由於2 >= 0return語句不會被調用。
  7. 調用方法reverse_append([],1)
  8. 由於1 >= 0return語句不會被調用。
  9. 調用方法reverse_append([],0)
  10. 由於0 >= 0return語句不會被調用。
  11. 調用方法reverse_append([],-1)
  12. 由於-1 < 0,返回數組([])。
  13. 我們在我們的調用堆棧中彈出一個級別,其中n = 0arr = []
  14. arr << n and arr is returned,so now now so arr = [0]
  15. 我們在我們的調用堆棧中彈出了一個級別,其中n = 1arr = [0]
  16. arr << n and arr is returned,so now now so arr = [0, 1]
  17. 我們在我們的調用堆棧中彈出一個級別,其中n = 2arr = [0, 1]
  18. arr << n and arr is returned,so now now now arr = [0, 1, 2]
  19. 我們在我們的調用堆棧中彈出一個級別,其中n = 3arr = [0, 1, 2]
  20. arr << narr被返回,所以現在arr = [0, 1, 2, 3]
  21. 我們在我們的調用堆棧中彈出一個級別,其中n = 4arr = [0, 1, 2, 3]
  22. arr << narr已退回,所以現在arr = [0, 1, 2, 3, 4]
  23. 最後,「頂級」方法返回,我們有我們的最終結果。
+0

真的有那麼多步驟嗎? o.o – 13aal

+1

@ 13aal我認爲人們在第一次瞭解遞歸函數時遇到的最大概念難點是簡單地通過一個例子,逐行並跟蹤實際發生的事情。所以是的,我的回答可能有點過頭了。但我希望它也會鼓勵讀者也這樣瀏覽代碼,以瞭解基本概念。 –

2

很好地使用提供的參數遍歷代碼。第一步是檢查它是否不是。如果不是0,則反向附加[],3,並將該數組追加到數組中,然後返回數組。

所以需要該陣列,在經過了處理[], 3[], 2,[],1[], 0的步驟後,添加4。因此,第一個會成功的調用只是在數組小於0時返回數組,接下來是0追加,然後是1,然後是2,然後是3,最後是4的原始調用將被添加arr << n

2

有一個很好的工具,你可以添加到許多編輯稱爲「Seeing Is Believing」,它可以讓你看到正在發生的事情爲運行代碼:

def reverse_append(arr, n) 
    return arr if n < 0 # => false, false, false, false, true 
    reverse_append(arr, n-1) # => [], [0], [0, 1], [0, 1, 2] 
    arr << n # => [0], [0, 1], [0, 1, 2], [0, 1, 2, 3] 
    arr # => [0], [0, 1], [0, 1, 2], [0, 1, 2, 3] 
end 

reverse_append([], 3) # => [0, 1, 2, 3] 

然而,像「reverse_append」的名稱似乎像你應該看到,在值下降的結果:

def reverse_append(arr, n) 
    return arr if n < 0 # => false, false, false, false, true 
    reverse_append(arr, n-1) # => [], [0], [1, 0], [2, 1, 0] 
    arr.unshift n # => [0], [1, 0], [2, 1, 0], [3, 2, 1, 0] 
    arr # => [0], [1, 0], [2, 1, 0], [3, 2, 1, 0] 
end 

reverse_append([], 3) # => [3, 2, 1, 0] 

在這兩種情況下,有很多更簡單的方法來產生這樣的陣列,而不依賴於遞歸:

[*0..3] # => [0, 1, 2, 3] 
(0..3).to_a # => [0, 1, 2, 3] 

[*0..3].reverse # => [3, 2, 1, 0] 
(0..3).to_a.reverse # => [3, 2, 1, 0]