Выполнение бинарного поиска по текстовому файлу с использованием Java

1

У меня есть большой текстовый файл около 1 миллиона слов. Я делаю это для Android-телефона, и я просто пытаюсь понять, существует ли слово в текстовом файле. Загрузка чего-либо в память не является вариантом. Память и процессор телефона Android настолько слабы, что чтение этого файла занимает около 20 секунд.

Я изменил этот текстовый файл на слова, чтобы быть на равной ширине. Каждое слово - 50 символов + 1 для новой строки. Тем не менее, я немного запутался в том, как правильно реализовать двоичный поиск, так как я все время путаюсь с тем, сколько байтов я должен добавить для работы seek() для правильной работы.

public static long search(RandomAccessFile file, String target)
            throws IOException {

    file.seek(0);
    String line = file.readLine();

    if(line.equals(target))
        return 1;

    long start = 0;
    long end = file.length();
    long mid = (start + end -50)/2;

    while(start <= end)
    {
        file.seek(mid);
        line = file.readLine();
        if(line.compareTo(target) < 0)
            start = mid + 51;
        else if(line.equalsIgnoreCase(target))
            return 1;
        else
            end = mid - 51;

        mid = (start + end)/2;
    }

    if(start > end)
        return 0;

    return -1;
}

В первый раз, когда я заканчиваю, я вычитаю 50, потому что у самого последнего слова нет новой строки. После нескольких итераций это перестает работать должным образом. Я не могу понять, как правильно выполнить эту работу. Может ли кто-нибудь направить меня на то, что я делаю неправильно?

  • 0
    Вы пытались использовать Trie?
  • 0
    Да, поверьте мне, я исчерпал все возможные решения. Загрузка чего-либо в память не является возможным решением. Чтение только самого файла, даже не сохраняя его, занимает 20 секунд.
Показать ещё 6 комментариев
Теги:
file
binary-search

1 ответ

2
Лучший ответ

Посредством обертки файла в AbstractList вы можете использовать внереализационную реализацию бинарного поиска:

final int size = (int) ((file.length() + LINE_BREAK_LEN) / (WORD_LEN + LINE_BREAK_LEN));
return Collections.binarySearch(
    new AbstractList<String>() {
        public String get(int pIdx) {
            try {
                file.seek((WORD_LEN + LINE_BREAK_LEN) * pIdx);
                return file.readLine();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }

        public int size() {return size;}
    },
    target,
    Comparator.comparing(String::toLowerCase)
);

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

  • 0
    Очень хорошая точка на разрыве линии! OP всегда может прочитать символы WORD_LEN и удалить миллион байтов из списка слов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню