Хорошо, давайте посмотрим на ваш код. Во-первых, небольшая подсказка: для размещения кода в stackoverflow (и на других сайтах stackExchange) лучше использовать только пробелы для отступов, поскольку вкладки выглядят плохо.
Итак, здесь снова ваш код, с правильными отступами (кстати, Emacs с JDEE сделал это - похоже, я не настроил его правильно, или у него были некоторые проблемы с вычислением вашего кода), и мои комментарии разбросаны.
public static int closestPairAux(Point[] X, Point[] Y)
Итак, еще раз вопрос: каковы значения этих двух массивов параметров? Содержат ли они оба одинаковые точки или другие? Почему вы даете оба массива? Когда вы ответите, дайте им лучшие имена.
Кроме этого, дайте вашему методу комментарий к документации. Какие аргументы он получает, что он возвращает? (Это не возвращает расстояние, но квадрат расстояния, если я правильно понимаю.)
throws TrivialClosestPairException, UnknownSortOptionException
{
if (X.length<4){
return PointSet.naiveClosestPair(new PointSet (X));
}
Хорошо, у вас есть конец рекурсии для маленьких массивов.
int V = X[(int) Math.ceil(( (double) X.length/2)-1)].getX();
Если я правильно понимаю, вы пытаетесь получить средний элемент массива здесь. Этот путь будет более понятным:
int middleIndex = X.length/2;
int V = X[middleIndex].getX();
В Java целочисленное деление работает путем округления до нуля - поэтому middleIndex
для массива длиной 20 или 21 равно 10. (Если вы хотите, чтобы в первом случае это было 9, вычтите 1 перед делением .)
Конечно, вы можете написать это как int V = X[X.length/2].getX();
, но вы сможете снова использовать middleIndex
в следующих двух утверждениях.
Point[] PL = Arrays.copyOfRange(X,(int) 0,(int) Math.ceil(X.length/2));
Point[] PR = Arrays.copyOfRange(X,(int) Math.floor(X.length/2), (int) X.length-1);
Как уже было сказано, перепишите эти два, используя middleIndex
, как и раньше. Вам также не нужно приводить 0
и X.length-1
к int, они уже есть. (И снова взгляните на документацию Arrays.copyOfRange - индекс to
является эксклюзивным.)
Итак, здесь вы разбиваете свой массив X на два (примерно) массива одинакового размера, хорошо.
int distance = Math.min(closestPairAux(PL,Y),closestPairAux(PR,Y));
Вот ваш рекурсивный вызов. Что ты здесь делаешь, на самом деле? Почему вы передаете эти параметры рекурсивному вызову? ( Специально, почему оба получают один и тот же массив Y? )
Point[] shortDist = new Point[Y.length];
int n = 0;
for (int i = 0; i <Y.length; i++)
{
int A = Y[i].getX();
if ((V-A)*(V-A) <= distance)
{
shortDist[n] = Y[i];
}
}
Итак, теперь вы проходите через свой массив Y, собирая те элементы, которые находятся рядом с разделителем, в вашем новом shortDist
массиве.
for (int i =0; i< shortDist.length -1; i++)
{
for (int r = i+1; r <shortDist.length-1 && r< i + 7; r ++){
d = Math.min(d, shortDist[i].sqrDist(shortDist[r]));
}
}
Является ли d
таким же, как distance
раньше?
return d;
}
Вообще, это похоже на реализацию вашего алгоритма, да. Подумайте немного о моих вопросах и, по крайней мере, запустите компилятор кода, чтобы убедиться, что в нем нет очевидных синтаксических ошибок (через опечатки).
Добавьте комментарии в свой код в нужных местах (перед блоком кода) и протестируйте свой алгоритм для некоторых (возможно, случайных) примеров входных данных, сравнивая его с реализацией naive (они должны возвращать оба одинаковых результата , но ваш, надеюсь, быстрее.)