#java #algorithm #sorting #mergesort
#java #алгоритм #сортировка #сортировка слиянием
Вопрос:
// merge operation for merge sort
private static void merge(int[] a, int left, int middle, int right) {
int[] temp = new int[right - left 1];
int leftCrawler = left, rightCrawler = middle;
int currentIndex = 0;
while (leftCrawler < middle amp;amp; rightCrawler <= right) {
if (a[leftCrawler] < a[rightCrawler])
temp[currentIndex ] = a[leftCrawler ];
else
temp[currentIndex ] = a[rightCrawler ];
}
while (leftCrawler < middle)
temp[currentIndex ] = a[leftCrawler ];
while (rightCrawler <= right)
temp[currentIndex ] = a[rightCrawler ];
// copy temp into a
for (int i = 0; i < temp.length; i )
a[i] = temp[i];
}
private static void mergeSort(int[] a, int left, int right) {
if (right > left) {
int middle = left (right - left) / 2;
mergeSort(a, left, middle);
mergeSort(a, middle 1, right);
merge(a, left, middle, right);
}
}
public static void mergeSort(int[] a) {
int left = 0, right = a.length - 1;
mergeSort(a, left, right);
}
Итак, я подумал, что проблема может быть в моей операции слияния, однако я протестировал ее на следующем массиве int[] a = {2, 5, 7, 15, 8, 9, 10}
с left = 0
, middle = 4
и right = a.length - 1
, и операция слияния успешно выполняет то, что ей нужно.
Я сравнил свою реализацию сортировки слиянием с теми, что есть на разных веб-сайтах, и я не могу заметить разницы. Моя сортировка слиянием не приведет к успешной сортировке массива. Что я делаю не так?
Ответ №1:
В вашем коде 3 ошибки:
-
цикл слияния не включает элемент at,
a[middle]
потому что вы используетеleftCrawler < middle
вместо:while (leftCrawler <= middle amp;amp; rightCrawler <= right)
-
второй цикл
while (leftCrawler < middle)
также должен быть изменен на:while (leftCrawler <= middle)
-
цикл для копирования из
temp
обратно вa
использует неверный индекс вa
. Это должно быть:// copy temp into a for (int i = 0; i < temp.length; i ) a[left i] = temp[i];
Обратите внимание, что первая ошибка коренится в используемом здесь вредоносном соглашении, где right
и middle
включены в срезы вместо исключенных. Исключение правильных границ позволяет упростить код без каких-либо подверженных ошибкам 1
/ -1
корректировок.
Вот измененная версия:
// merge operation for merge sort
private static void merge(int[] a, int left, int middle, int right) {
int[] temp = new int[right - left];
int leftCrawler = left, rightCrawler = middle;
int currentIndex = 0;
while (leftCrawler < middle amp;amp; rightCrawler < right) {
if (a[leftCrawler] < a[rightCrawler])
temp[currentIndex ] = a[leftCrawler ];
else
temp[currentIndex ] = a[rightCrawler ];
}
while (leftCrawler < middle)
temp[currentIndex ] = a[leftCrawler ];
while (rightCrawler < right)
temp[currentIndex ] = a[rightCrawler ];
// copy temp into a
for (int i = 0; i < temp.length; i )
a[left i] = temp[i];
}
private static void mergeSort(int[] a, int left, int right) {
if (right - left >= 2) {
int middle = left (right - left) / 2;
mergeSort(a, left, middle);
mergeSort(a, middle, right);
merge(a, left, middle, right);
}
}
public static void mergeSort(int[] a) {
mergeSort(a, 0, a.length);
}
Ответ №2:
Проблема может быть в вашей копии:
// copy temp into a
for(int i = 0; i < temp.length; i )
a[i] = temp[i];
Что вы, вероятно, хотите (обратите внимание на left i
):
// copy temp into a
for(int i = 0; i < temp.length; i )
a[left i] = temp[i];
(Ваш тест не обнаружил проблему, так как left
было 0.)
Комментарии:
1. Я внес изменения, и мой входной массив остался точно таким же. Я признаю, что это изменение было необходимо, но я все еще не сортирую массив.