簡體   English   中英

使用遞歸的StackOverflowError

[英]StackOverflowError using Recursion

我應該比較一個遞歸函數和一個非遞歸函數,看看哪個對一個類項目更快。 教授還希望當迭代器等於10,100,1000等時,以毫秒為單位對迭代進行計時。我雖然可以正常工作,但是在C ++獲取計時器方面遇到了很多麻煩,所以我改用Java了,更容易獲得毫秒輸出。

但是現在當我嘗試使用超過8,000的任何數字時,我從遞歸算法中得到了一個很大的胖堆棧溢出錯誤。 誰能給我任何見識? 獎勵:我也無法像在非遞歸中那樣弄清楚如何在遞歸函數中執行計時器。 我將如何處理?

public class comparingTimes {
    public static void main(String[] args) {

        double num = 10000;
        double result;
        nonRec(num); 
        result = rec(num);      
        System.out.printf("Rec %.0f",(result));
    }
    public static void nonRec(double num)
    {
    double resultNum = 1;
    double total = 0;
    long startTime = System.currentTimeMillis();
    long endTime;
    for (double i = 1; i < num; i++)
     {
        total += i * (i+1);
        if (i == resultNum)
        {
            endTime = System.currentTimeMillis();
            System.out.printf("Total execution time: %f seconds - num = %.0f%n", (endTime - startTime)/1000.0, i);
            resultNum *= 10;
        }           
     }      
    System.out.printf("NonRec: %.0f%n", total); 
}
public static double rec(double num)
{
    if (num == 0)
        return 0;
    else            
        return num * (num-1) + rec(num-1);      
}
}

遞歸的理想用例是在每個遞歸級別上大量減少“搜索空間”時。 例如,考慮一個二進制搜索,其中每個遞歸級別將剩余的搜索空間減半。

您的特殊問題是您嘗試執行8000級遞歸,因為每個級別只會遞減值。 這將需要相當大的堆棧空間。

您可以考慮使用-ss-oss選項來增加JVM的堆棧大小(當然取決於實現)。 但這只會給您帶來很多好處。

在安排整個遞歸操作的時間方面,我只需將頂級調用之前的時間存儲在main() ,然后將其與頂級調用返回的時間進行比較,例如:

long startTime = System.currentTimeMillis();
result = rec(num);
long endTime = System.currentTimeMillis();
// Now calculate the elapsed time.

無需嘗試在遞歸調用本身中進行操作。

如果你想遞歸調用在某些點上做到這一點,你可以初始化一個“全局”計數器變量(一個遞歸本身,如類級別靜態變量外)為0,並有遞歸函數增加它的每遞歸級別。

然后讓它在您感興趣的點輸出時間變化量,例如變量設置為10、100、1000等時。

嘗試增加堆棧大小

至於測量時間

public static void main(String[] args) {

    double num = 10000;
    double result;
    long start = System.currentTimeMillis();
    nonRec(num); 
    long finish = System.currentTimeMillis();
    System.out.println("Time taken (non-recursive): " + (finish -start));
    start = System.currentTimeMillis();
    result = rec(num);      
    finish = System.currentTimeMillis();
    System.out.println("Time taken (recursive): " + (finish -start));
    System.out.printf("Rec %.0f",(result));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM