#java #mergesort
#java #сортировка слиянием
Вопрос:
Я просматривал приведенный ниже пример программы и пытался понять, как работает приведенная ниже рекурсия, я не мог понять, как сортируются левые и правые элементы массива, и, наконец, слияние двух подмассивов, как показано ниже. Любое наглядное объяснение приведенного ниже метода было бы очень полезным, поскольку я пытаюсь понять приведенный ниже рекурсивный код.
public static int[] mergeSort(int[] arrayToSort) {
// BASE CASE: arrays with fewer than 2 elements are sorted
if (arrayToSort.length < 2) {
return arrayToSort;
}
// STEP 1: divide the array in half
// we use integer division, so we'll never get a "half index"
int midIndex = arrayToSort.length / 2;
int[] left = Arrays.copyOfRange(arrayToSort, 0, midIndex);
int[] right = Arrays.copyOfRange(arrayToSort, midIndex, arrayToSort.length);
// STEP 2: sort each half
int[] sortedLeft = mergeSort(left);
int[] sortedRight = mergeSort(right);
// STEP 3: merge the sorted halves
int[] sortedArray = new int[arrayToSort.length];
int currentLeftIndex = 0;
int currentRightIndex = 0;
for (int currentSortedIndex = 0; currentSortedIndex < arrayToSort.length;
currentSortedIndex ) {
// sortedLeft's first element comes next
// if it's less than sortedRight's first
// element or if sortedRight is exhausted
if (currentLeftIndex < sortedLeft.length
amp;amp; (currentRightIndex >= sortedRight.length
|| sortedLeft[currentLeftIndex] < sortedRight[currentRightIndex])) {
sortedArray[currentSortedIndex] = sortedLeft[currentLeftIndex];
currentLeftIndex ;
} else {
sortedArray[currentSortedIndex] = sortedRight[currentRightIndex];
currentRightIndex ;
}
}
return sortedArray;
}
Ответ №1:
Сортировка выполняется в цикле слияния:
- если массив очень маленький (0 или 1 элемент),
mergeSort()
возвращает его немедленно. - в противном случае он разбивает массив на 2 подмассива примерно одинакового размера,
left
иright
, которые сортируются путем рекурсивного вызова одного и того же метода:// STEP 2: sort each half int[] sortedLeft = mergeSort(left); int[] sortedRight = mergeSort(right);
- на последнем шаге выполняется итерация по отсортированным половинкам для создания нового отсортированного массива.
Рекурсивные вызовы завершаются, потому что они выполняются только с подмассивами, строго меньшими, чем массив аргументов.
Комментарии:
1. Возможно, было бы проще объяснить, что фактическое слияние не происходит до тех пор, пока вложенное рекурсивное разделение не приведет к двум подмассивам размером по 1 элементу каждый, после чего эти два подмассива объединяются для создания отсортированного подмассива с 2 элементами. Затем разделение и слияние выполняются по цепочке вызовов, сначала глубина, сначала слева.
2. @chqrlie: Спасибо. Я мог понять, что вы объяснили, поскольку то же самое было объяснено в терминах комментария в запросе. Чего я не понимаю, так это того, что рекурсивный вызов, как сортируются 2 подмассива и как два отсортированных подмассива окончательно объединяются с использованием рекурсии. Я попытался понять на примере: arrayToSort имеет 11 элементов, скажем {4,1,-2, 0, 4, 6, 7, 2, 5, 3, 8}. left имеет 5, а right — 6 элементов, скажем, — left : {4,1,-2, 0, 4} иправильно : {6, 7, 2, 5, 3, 8}.. Как они сортируются по отдельности и объединяются. Спасибо.