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. 尾遞歸函數
- 5. Scheme中的遞歸函數總是進行尾調優化?
- 6. 避免將積累參數在尾遞歸調用
- 7. 這個Scheme是否函數尾遞歸?
- 8. 是這個函數尾遞歸嗎?
- 9. Racy尾遞歸函數
- 10. Scala:尾遞歸函數
- 11. 可以函數尾遞歸
- 12. 尾遞歸函數與否
- 13. 嵌套遞歸是可能的還是應該避免遞歸?
- 14. 避免遞歸bannerView:didFailToReceiveAdWithError:iPad上
- 15. 避免遞歸調用.ajax();
- 16. 單遞函數中的尾遞歸
- 17. 遞歸函數總是返回空
- 18. 使用遞歸函數時避免字符串+整數加法
- 19. 我應該避免使用Prolog和一般的尾遞歸嗎?
- 20. 尾遞歸是否需要累加器?
- 21. C:中的遞歸函數總是有必要的嗎?
- 22. 使用C++中的尾遞歸函數計算列表總和
- 23. 在遞歸python函數中避免「內存不足」錯誤
- 24. 在R中覆蓋函數避免無限遞歸
- 25. 避免重新綁定函數參考中的遞歸
- 26. 部分尾遞歸函數是否仍然可以獲得完全尾遞歸函數的優化優勢?
- 27. 優化非尾遞歸函數
- 28. 如何使這個函數尾遞歸?
- 29. 藥劑尾調用遞歸函數
- 30. Memoizing尾調用優化遞歸函數
聽起來不錯,但現在歡迎來到現實世界。你寫一個遞歸函數而不是迭代函數。編譯器不會將其轉換爲迭代的。它會一直工作,直到您遇到足夠長的輸入。你的同事過來解釋你是多麼的錯誤。你重寫它。 – sharptooth 2010-07-20 11:42:30
這實際上取決於你對環境的瞭解以及函數在迭代形式中的邪惡/無邪。當然是務實的。我認爲,尾遞歸函數並不總是可以避免的。 – 2010-07-20 11:53:14
謝謝,fd。你和其他答覆者已經解釋了爲什麼使用尾遞歸有時是有意義的。 – AbdullahC 2010-07-20 12:21:46