Stackoverflowerror в реализации Quicksort - PullRequest
0 голосов
/ 11 мая 2018
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 возникает из-за проблемы с использованием рекурсии.В этом случае моя ошибка исходит из

Исключение в потоке "main" java.lang.StackOverflowError в quicksort.Quicksort.quickSort (Quicksort.java:36)

, что ..

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

Ответы [ 3 ]

0 голосов
/ 11 мая 2018
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 в методе разбиения. Спасибо всем, кто ответил и попытался помочь мне.

0 голосов
/ 11 мая 2018

Быстрая сортировка в среднем O (n log (n)) сложность.Тем не менее, его худший случай - O (n ^ 2).Это также относится к «глубине» рекурсивных вызовов.

Средний случай, когда глубина равна log (n), что для 40000 чисел составляет около 15. Поэтому, когда каждая рекурсия вызывает сама себя, каждый раз разбивая текущий фрагмент массивапополам глубина достигает примерно 15.

В худшем случае: вы делаете опору последним элементом в текущем фрагменте.При втором запуске быстрой сортировки числа уже отсортированы.Так что пивот в любом случае заканчивается в конце, и ваш массив разбивается на 2 части.Один - это элементы массива с 1 по 39999, а другой - просто элемент 40000. Поздравляем, вы успешно нашли Quicksorts в худшем случае.Глубина «левой» стороны всех вызовов будет 40 000.

Таким образом, когда метод вызывает другой метод, информация помещается в стек.При первом запуске в стек помещается относительно немного.Во втором случае 40 000 вызовов методов помещаются в стек, что приводит к переполнению.

0 голосов
/ 11 мая 2018

@ mackycheese21 Когда я говорю, что он работает нормально, я имею в виду, если я использую меньший массив, который я могу распечатать и посмотреть, он распечатает его отсортированным. То же самое с сортировкой 40000 случайных целых чисел, пока я не попытаюсь отсортировать уже отсортированный массив.

Так что, я думаю, вы просто хотите проверить, отсортирован ли массив. Поскольку это не кажется очень эффективным, единственное, о чем я могу думать, это то, что ваш метод partition для отсортированных массивов дает первый или последний индекс - то, что при разбиении дает пустой массив и полный массив. Это, вероятно, приводит к бесконечной рекурсии.

Я бы порекомендовал вам просто добавить отметку в partition, чтобы проверить, идет ли индекс к первому или последнему индексу, а затем, если это произойдет, просто разбить на середину.

...