簡體   English   中英

Quicksort實施中的StackoverflowError

[英]Stackoverflowerror in Quicksort implementation

import java.util.Random;

public class Quicksort {

    private int partition(int arr[], int first, int last) {

    int pivot = arr[last]; //Using last element as pivot
    int i = (first-1);//index of smaller element

    for (int j = first; j < last; j++) {
        //if current element is smaller than or equal to pivot
        //then swap the elements
        if (arr[j] <= pivot) {
            i++;
            //swapping occurs here
            //make a temp variable to the first element
            //swap arr[j] and arr[i]
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            //i++;
        }
    }
    int temp = arr[i+1];
    arr[i+1] = arr[last];
    arr[last] = temp;
    return i+1;
}

private void quickSort(int arr[], int first, int last) {

    if (first < last) {
        int pivindex = partition(arr, first, last);
        quickSort(arr, first, pivindex-1);
        quickSort(arr, pivindex+1, last);
    }
}

public void sort(int[] arr) {
    quickSort(arr, 0, arr.length - 1);
}

public static int[] getRandoms(int count) {
    return new Random().ints().limit(count).toArray();
}

public static void main(String[] args) {
    Quicksort fix = new Quicksort();

    int[] randoms = getRandoms(40000);
    double startTime = System.currentTimeMillis();
    fix.sort(randoms);    
    double endTime = System.currentTimeMillis();
    System.out.println("Performance Time on Random Data:" + (endTime - startTime));

    //Benchmarking quicksort on already sorted data
    startTime = System.currentTimeMillis();
    fix.sort(randoms);
    endTime = System.currentTimeMillis();
    System.out.println("Performance Time on Sorted Data:" + (endTime - startTime));

}
}

我不完全確定為什么會收到StackoverflowError。 當我只排序一次時,代碼運行良好,但是,如果我嘗試對同一數據進行兩次排序,那就是出現錯誤。

我了解發生Stackoverflowerror是因為使用遞歸存在問題。 在這種情況下,我的錯誤來自

quicksort.Quicksort.quickSort(Quicksort.java:36)處的線程“ main”中的異常java.lang.StackOverflowError

是..

if (first < last) {
        int pivindex = partition(arr, first, last);
        quickSort(arr, first, pivindex-1);
        quickSort(arr, pivindex+1, last);
    }

@ mackycheese21當我說它運行良好時,我的意思是,如果我使用可以打印並看到的較小數組,它將按排序將其打印出來。 排序40,000個隨機整數也是如此,直到我嘗試對已經排序的數組進行排序。

所以我想您只是想檢查數組是否已排序。 因為這看起來效率不高,所以我能想到的唯一另一件事是,您的partition方法是對有序數組給出第一個或最后一個索引-進行分區時給出一個空數組和整個數組。 這可能導致無限遞歸。

我建議您只添加一個檢入partition以檢查索引是指向第一個還是最后一個索引,然后如果確實發生了,就在中間拆分。

QuickSort的平均復雜度為O (n log(n))。 但是,最壞的情況是O (n ^ 2)。 這也與遞歸調用的“深度”有關。

平均情況下,深度為log(n),對於40,000個數字而言,深度約為15。因此,當每次遞歸調用自身時,每次將當前數組分割成兩半時,深度都會達到15。

最壞的情況:將樞軸作為當前片段的最后一個元素。 第二次運行quicksort時,數字已經排序。 因此,無論如何樞軸最終都將結束,並且您的陣列被分成2個部分。 一個是數組元素1到39999,另一個是元素40000。恭喜,您已經成功找到Quicksorts最壞的情況。 所有通話的“左側”深度為40,000。

因此,當一個方法調用另一個方法時,信息被壓入堆棧。 在第一輪中,很少有人被推入堆棧。 在第二種情況下,將40,000個方法調用壓入堆棧,從而導致溢出。

private int partition(int arr[], int first, int last) {

int pivot = arr[last]; //Using last element as pivot
int i = (first-1);//index of smaller element

for (int j = first; j < last; j++) {
    //if current element is smaller than or equal to pivot
    //then swap the elements
    if (arr[j] <= pivot) {
        i++;
        //swapping occurs here
        //make a temp variable to the first element
        //swap arr[j] and arr[i]
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        //i++;
    }
}
int temp = arr[i+1];
arr[i+1] = arr[last];
arr[last] = temp;
return i+1;
}

我發現問題出在分區方法的for循環中。 謝謝,所有回答並嘗試幫助我的人。

暫無
暫無

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

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