更新:請注意,現在這個問題沒有多大意義,因爲callstack將獨立於類型T而增長。callstack完全取決於正在處理的列表中的節點數 - 這些數據包含在節點對調用堆棧的大小沒有影響。遞歸使用多少堆棧(從列表中刪除節點)?
比方說,我有一個遞歸java實現了「刪除節點 - 從列表」的方法看起來是這樣的:
// head
public void remove(T data) {
if (data == null)
throw new IllegalArgumentException();
head = remove(head, data);
}
// other nodes of list
private ListNode remove(ListNode current, T data) {
if (current == null)
return null;
if (current.data.compareTo(data) == 0)
return current.next;
current.next = remove(current.next, data);
return current;
}
讓我們進一步假設該類型T
是int
我的問題是:與我正在處理的列表大小相比,調用堆棧會得到多少(在最壞的情況下)?
什麼我至今認爲: 從我所看到的Java 8不優化遞歸(?右我的整個分析假設這是真的)。因此,我們將有一個與列表大小成線性增長的調用堆棧。
更確切地說:這個方法remove(ListNode current, T data)
將基本上在我的列表中的每個節點的調用堆棧上放置一個節點引用(32位位置上的32位)和一個int
(也是32位)。
現在,由於列表中的一個節點也由一個引用和一個節點構成,因此節點實際上與其中一個遞歸調用的大小几乎相同。實際上,其中一個調用甚至可能會佔用更多空間(返回地址也必須被推入堆棧,對嗎?或者可以通過某種方式進行優化?)。
所以,如果我是正確的,那麼在最壞情況下(當要移除的元素是列表中的最後一個時),callstack基本上會像列表本身一樣大!這是真的嗎?如果我是正確的,那麼就處理int
列表所需的堆棧而言,這意味着1或甚至更大的因子!因此,當處理大型列表時(實際上並不那麼大),比如說1M人將獲得一個stackoverflow,如果用stacksize(0.5M)的默認設置運行的話,我會得到一個stackoverflow。我知道這樣一個事實,對於更大的數據類型來說,這個因子會更少,但是我仍然堅信在任何情況下基本上都是這樣的:如果沒有進行優化,那麼callstack將隨着列表大小線性增長 - 因此一個應該更喜歡遞歸過程的迭代。
一般來說,我會說,這個callstack將會以一個因子(size_of_all_arguments_in_call + size_of_return_address)/size_of_a_single_listelement
粗略線性增長,在int
列表的情況下,它幾乎是一樣的,對吧?請不要誤解我的size_of_all_arguments
:我知道我們只傳遞對這些調用中對象的引用的值,而不是整個對象本身。因此,對於大型物體來說,這個因素可能不會那麼戲劇化,但我仍然認爲不應該接受不必要的線性空間開銷。但是,對於int
的列表,該因子將是約。 1.
這個分析是否正確,或者我錯過了什麼?
背景:我與討論這樣做的人,試圖說服我,在Java調用堆棧不會那麼顯着增長,並指出我缺少明顯的東西(很遺憾沒能告訴我什麼,對我來說真的不是很明顯的話) - 因爲我不知道它是什麼,我很想念我渴望學習;)
相關:
在我相關的問題,缺少的主要事情是多少空間將調用堆棧實際使用從
我不知道如果JVM帳戶的東西,但你可以看到這篇文章和鏈接的重複http://stackoverflow.com/questions/17250883/is-it-possible-to-determine-how-much -space-is-on-the-stack –
找到了Java問題http://stackoverflow.com/questions/20030120/java-default-stack-size –
我認爲你還需要考慮這個框架的大小: http://www.herongyang.com/JVM/Stack-Overflow-and-JVM-Stack-Frame.html – Lee