StackruError в рекурсивном бинарном поиске в файле в Java

filepointer застревает в точке, в результате чего StackruError, Можете ли вы указать мне, что именно здесь не так? Ошибка именно такова: java.lang.StackruError

Я пытаюсь найти местоположение, так как ширина записи не фиксирована.

Вот кусок кода:

private static void binarySearch(RandomAccessFile raf, String searchvalue, Long low, Long high) throws IOException
{
    Long middle = (low + high) / 2;
    Long mreal = null;
    if(low > raf.length() -1 || high > raf.length()-1 || low >= high) {
        System.out.println("Element not found:");   return ;
    }

    StringBuilder sb = new StringBuilder();
    for(long filePointer = middle; filePointer != -1; filePointer--) {
        raf.seek(filePointer);
        int readByte = raf.readByte();
        if(readByte == 0xA) {
            break;
        }

        sb.append((char)readByte);
    }

    String lastLine = sb.reverse().toString();
    System.out.println(lastLine);

    mreal = raf.getFilePointer();
    String str = raf.readLine();
    System.out.println(str);

    String values[] = str.split("\t",-1);
    int compared = searchvalue.compareTo(values[fieldindex]);
    System.out.println(fieldindex);

    if(compared == 0) {
        System.out.println("Value found. The other details:");
        for(int i=0; i < values.length;i++)
        System.out.print("\t" +  values[i]);
        return;
    } else if(compared < 0)
        binarySearch(raf,searchvalue,low,mreal-1);
    else if(compared > 0)
        binarySearch(raf,searchvalue,mreal,high);
}

Трассировки стека:

Исключение в потоке "основной" java.lang.StackruError

>at java.util.regex.Pattern$Node.<init>(Pattern.java:2993)
    >at java.util.regex.Pattern$CharProperty.<init>(Pattern.java:3332)
    >at java.util.regex.Pattern$CharProperty.<init>(Pattern.java:3332)
    >at java.util.regex.Pattern$BmpCharProperty.<init>(Pattern.java:3363)
    >at java.util.regex.Pattern$BmpCharProperty.<init>(Pattern.java:3363)
    >at java.util.regex.Pattern$Single.<init>(Pattern.java:3391)
    >at java.util.regex.Pattern.newSingle(Pattern.java:2951)
    >at java.util.regex.Pattern.atom(Pattern.java:1985)
    >at java.util.regex.Pattern.sequence(Pattern.java:1885)
    >at java.util.regex.Pattern.expr(Pattern.java:1752)
    >at java.util.regex.Pattern.compile(Pattern.java:1460)
    >at java.util.regex.Pattern.<init>(Pattern.java:1133)
    >at java.util.regex.Pattern.compile(Pattern.java:823)
    >at java.lang.String.split(String.java:2292)

1 ответ

else if(compared > 0)
    binarySearch(raf,searchvalue,mreal,high);

Это должно быть mreal + 1.

Кроме того, рекурсия избыточна для бинарного поиска.... обычно цикл быстрее.

Рольф

EDIT:====

ОК, так что все равно не работает. Это потому что я был только отчасти прав. Я только на мгновение посмотрел на код и увидел проблему, но потом исправил ее с неверным значением.

Вместо добавления 1, вы должны добавить количество символов в строке, с которой вы сравниваете, плюс конец строки (если есть - это может быть последняя строка...).

Все это говорит мне о том, что это, вероятно, домашнее задание... и упражнение по рекурсии и изучение бинарного поиска.

Не выполняя за вас домашнее задание, я проведу минуту, критикуя ваш код.

Предполагается, что бинарный поиск находит среднюю точку, а затем, если средняя точка совпадает, возвращает ее, если она больше, чем поиск, а затем выполняет поиск до средней точки, в противном случае выполняется поиск после средней точки.

Ваш код получает среднюю точку "правильно", а "до" - правильно, но он не ищет "после"... потому что вы не вычисляете "после" справа. Вы должны быть "после" целая строка, а не только после первого символа. Почини это. Помните, что использование readLine() означает, что вы не знаете терминатор строки (это '\r\n' или просто '\n'?). Я рекомендую использовать цикл после "средней" точки, а затем идти вперед, пока не дойдете до другого \ n, а затем использовать это (+1) для вычисления позиции поиска "после", если вам это нужно.

Некоторые другие комментарии....

  • Не используйте "автобокс". Используйте длинные примитивы вместо длинных объектов.
  • Зачем вызывать getFilePointer(), когда возвращаемое значение уже известно в переменной filepointer.
  • При вычислении "среднего", используйте "низкий + высокий" >>> 1 ...., он поразит вашего лектора, и вы можете сказать, что знаете, почему, прочитав это: http://googleresearch.blogspot.ca/2006/06/extra-extra-read-all-about-it-nearly.html
  • Пока вы читаете это, вы можете понять, почему двоичный поиск в цикле лучше, чем в рекурсии.
  • если вы используете рекурсию, вы должны установить свои параметры в 'final', потому что это оставляет меньшую площадь в стеке, и вы можете идти 'глубже'.
  • если вы используете рекурсию, то вы должны минимизировать объекты, которые вы создаете в своем методе... как StringBuilders....

Рольф

Другие вопросы по тегам