У меня возникла проблема с разделением при попытке реализовать алгоритм Quicksort. Моя реализация работает хорошо с массивами размером до 10 000, но над тем, что я получаю StackOverflowError. Обратите внимание, что это происходит только тогда, когда входные массивы находятся в порядке убывания. Случайно упорядоченные массивы могут быть до 10 000 000 000, прежде чем они вызывают одну и ту же проблему.Рекурсия вызывает переполнение стека
Я уверен, что в части есть что-то не так, когда я разбиваю массив, но я не могу понять, что случилось. Я пробовал отлаживать, но не имел успеха с поиском проблемы. Я понимаю, что ошибка вызвана слишком большим количеством рекурсивных вызовов, но, насколько я знаю, стек не должен переполняться, если разделение хорошо реализовано.
Заранее спасибо :)
Мой код:
public void sort(int[] v, int first, int last) {
if (first >= last) return;
//less than two elements left in subvector
// Partition the elements so that every number of
// v[first..mid] <= p and every number of v[mid+1..last] > p.
int[]subvector = new int[2];
subvector = partition(v, first, last);
sort(v, first, subvector[0]-1);
sort(v, subvector[1], last);
}
И метод разделения:
private int[] partition(int[] v, int first, int last) {
int low = first;
int mid = first;
int high = last;
int pivot = getPivot(v, last);
while (mid <= high) {
// Invariant:
// - v[first..low-1] < pivot
// - v[low..mid-1] = pivot
// - v[mid..high] are unknown
// - v[high+1..last] > pivot
//
// < pivot = pivot unknown > pivot
// -----------------------------------------------
// v: | | |a | |
// -----------------------------------------------
// ^ ^ ^ ^ ^
// first low mid high last
//
int a = v[mid];
if (a < pivot) {
v[mid] = v[low];
v[low] = a;
low++;
mid++;
} else if (a == pivot) {
mid++;
} else { // a > pivot
v[mid] = v[high];
v[high] = a;
high--;
}
}
return new int[]{low, high};
}
Да, эта конкретная версия выбирает последний элемент подвектора. Таким образом, вы имеете в виду, что если я выберу лучший стержень (например, случайный/медианный), рекурсия не будет такой глубокой? Я тогда предполагаю, что нет ничего плохого в разделении и просто большие числа, которые вызывают переполнение? – proah
@proah: Разработайте на бумаге то, что происходит с точки зрения поворота и рекурсии с отсортированным списком, когда вы выбираете самый высокий или самый низкий элемент. Обратите внимание, что в этом случае происходит небольшая «сортировка». Затем посмотрите, что произойдет, если вы выберете медианный элемент или случайный элемент. –
Понял, сделаю это! Спасибо за Ваш ответ. – proah