4
A
回答
6
如果您使用的編譯器語言優秀,那麼可以優化這些類型的遞歸,所以在這些情況下,如果它提高了使用遞歸的可讀性,我會說堅持下去。
1
這取決於語言,但往往開銷並不大。這可能是主觀的,但遞歸函數往往更易於理解。大多數情況下,您不會注意到性能差異。
我會去尋找尾遞歸,除非我的平臺在處理它時非常糟糕(即根本沒有這樣做,但總是推入棧中)。
6
不,這並非總是如此。許多語言和/或編譯器可以輕鬆地優化尾遞歸調用,並將其重寫爲迭代版本,或以某種方式重用堆棧幀以用於後續調用。
Scheme語言任務,落實使用tail call optimization
GCC可以優化尾調用爲好,考慮在一個鏈表釋放所有節點的功能:
void free_all(struct node *n)
{
if(n != NULL) {
struct node *next = n->next;
free(n);
free_all(next);
}
}
編譯成,與優化:
free_all:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8(%ebp), %eax
testl %eax, %eax
je .L4
.p2align 4,,7
.p2align 3
.L5:
movl 4(%eax), %ebx
movl %eax, (%esp)
call free
testl %ebx, %ebx
movl %ebx, %eax
jne .L5
.L4:
addl $20, %esp
popl %ebx
popl %ebp
ret
也就是說,一個簡單的跳躍,而不是recursivly調用free_all
+0
Upvoted爲實際示例。 – jrockway 2010-10-06 21:41:21
2
第
爲了便於閱讀,許多計算可以更好地表達爲遞歸(尾部或其他)函數。如果你的編譯器沒有進行尾部調用優化,並且你希望你可能吹掉調用堆棧,唯一的原因是避免它們。
相關問題
- 1. 避免遞歸
- 2. 避免遞歸
- 3. 尾遞歸函數
- 4. Scheme中的遞歸函數總是進行尾調優化?
- 5. 避免將積累參數在尾遞歸調用
- 6. 可以函數尾遞歸
- 7. 是這個函數尾遞歸嗎?
- 8. 嵌套遞歸是可能的還是應該避免遞歸?
- 9. 避免遞歸bannerView:didFailToReceiveAdWithError:iPad上
- 10. 使用遞歸函數時避免字符串+整數加法
- 11. 使用C++中的尾遞歸函數計算列表總和
- 12. 避免重新綁定函數參考中的遞歸
- 13. 部分尾遞歸函數是否仍然可以獲得完全尾遞歸函數的優化優勢?
- 14. CPS/Continuations StackOverflowError(尾 - )遞歸函數
- 15. 我的rec函數尾遞歸嗎?
- 16. 優化非尾遞歸函數
- 17. Memoizing尾調用優化遞歸函數
- 18. 遞歸SQL函數需要
- 19. 將遞歸函數轉換爲尾遞歸
- 20. 科特林:尾遞歸的相互遞歸函數
- 21. 數字的遞歸函數總和R
- 22. 在Haskell中避免顯式遞歸
- 23. 如何避免super()的無限遞歸?
- 24. 在遞歸中避免Stackoverflow的技巧
- 25. 如何避免遞歸堆棧溢出?
- 26. 如何避免遞歸依賴屬性
- 27. 避免RxJS5可觀察量的遞歸
- 28. 遞歸的深淺解析器 - 避免左遞歸
- 29. 有沒有辦法避免不必要的遞歸?
- 30. Javascript尾遞歸
聽起來不錯,但現在歡迎來到現實世界。你寫一個遞歸函數而不是迭代函數。編譯器不會將其轉換爲迭代的。它會一直工作,直到您遇到足夠長的輸入。你的同事過來解釋你是多麼的錯誤。你重寫它。 – sharptooth 2010-07-20 11:42:30
這實際上取決於你對環境的瞭解以及函數在迭代形式中的邪惡/無邪。當然是務實的。我認爲,尾遞歸函數並不總是可以避免的。 – 2010-07-20 11:53:14
謝謝,fd。你和其他答覆者已經解釋了爲什麼使用尾遞歸有時是有意義的。 – AbdullahC 2010-07-20 12:21:46