Реализация бинарного поиска по массиву строк

У меня есть проблемы с этим. Массив ввода основан на вводе файла, а размер массива определяется первой строкой в ​​файле. Метод binarySearch выглядит хорошо, но, похоже, не работает. Кто-нибудь сможет помочь? Благодарю.

public static int binarySearch(String[] a, String x) {
    int low = 0;
    int high = a.length - 1;
    int mid;

    while (low <= high) {
        mid = (low + high) / 2;

        if (a[mid].compareTo(x) < 0) {
            low = mid + 1;
        } else if (a[mid].compareTo(x) > 0) {
            high = mid - 1;
        } else {
            return mid;
        }
    }

    return -1;
}

public static void main(String[] args) {

    Scanner input = new Scanner(System.in);

    System.out.println("Enter the name of your file (including file extension): ");
    String filename = input.next();

    String[] numArray;
    try (Scanner in = new Scanner(new File(filename))) {
        int count = in.nextInt();

        numArray = new String[count];

        for (int i = 0; in.hasNextInt() && count != -1 && i < count; i++) {
            numArray[i] = in.nextLine();
        }

        for (int i = 0; i < count; i++) //printing all the elements
        {
            System.out.println(numArray[i]);
        }

        String searchItem = "The";

        System.out.println("The position of the String is:");
        binarySearch(numArray, searchItem);

    } catch (final FileNotFoundException e) {
        System.out.println("That file was not found. Program terminating...");
        e.printStackTrace();

    }

}

6 ответов

Я добавил следующий пример для вашего дальнейшего использования.

import java.util.Arrays;

public class BinaryStringSearch {

    public static void main(String[] args) {

        String array[] ={"EWRSFSFSFSB","BB","AA","SDFSFJ","WRTG","FF","ERF","FED","TGH"};
        String search = "BB";

        Arrays.sort(array);

        int searchIndex = binarySearch(array,search);

        System.out.println(searchIndex != -1 ? array[searchIndex]+ " - Index is "+searchIndex : "Not found");
    }

    public static int binarySearch(String[] a, String x) {
        int low = 0;
        int high = a.length - 1;
        int mid;

        while (low <= high) {
            mid = (low + high) / 2;

            if (a[mid].compareTo(x) < 0) {
                low = mid + 1;
            } else if (a[mid].compareTo(x) > 0) {
                high = mid - 1;
            } else {
                return mid;
            }
        }

        return -1;
    }

}

Надеюсь, это поможет:

 public static void main(String ar[]){

    String str[] = {"account","angel","apple","application","black"};
    String search= "application";
    int length = str.length-1;
    BinarySearchInString findStrin = new BinarySearchInString();
    int i = findStrin.find(str, 0, length, search);
    System.out.println(i);
}

  public int find(String first[], int start, int end, String searchString){
    int mid = start + (end-start)/2;

    if(first[mid].compareTo(searchString)==0){
        return mid;
    }
    if(first[mid].compareTo(searchString)> 0){
        return find(first, start, mid-1, searchString);
    }else if(first[mid].compareTo(searchString)< 0){
        return find(first, mid+1, end, searchString);
    }
    return -1;
  }

Как заметил @Mike Rylander, вы забыли вывести результат.

Вы должны использовать Arrays.binarySearch вместо вашей собственной реализации.

(Как правило, библиотеки JRE хорошо протестированы, хорошо документированы и быстры. Я гуглил "бинарный поиск Java", и этот вопрос хорошо ранжирован. Я попытался с кодом @Thusitha Indunil, который, похоже, не работать. Я погуглил и нашел Arrays.binarySearch, который работал.)

Я считаю, что ваша проблема в том, что вы забыли вывести результаты. Попробуйте заменить binarySearch(numArray, searchItem); с System.out.println(binarySearch(numArray, searchItem));

          int low = fromIndex;
    int high = toIndex - 1;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        Comparable midVal = (Comparable) a[mid];

        int cmp = midVal.compareTo(key);

        if (cmp < 0)
            low = mid + 1;
        else if (cmp > 0)
            high = mid - 1;
        else
            return mid;
    }
    return -(low + 1);
}

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

1: у вас есть String[] называется numArray и вы ищете String, "The" имя numArray возможно, немного ошибочен.

2: я предполагаю, что у вас есть какой-то определенный формат входного файла, где число String в файле указаны integer как первый токен в файле. Это нормально, однако, как условие в цикле for, который заполняет numArray есть in.hasNextInt()и следующий токен извлекается из Scanner с помощью in.nextLine(), Вы должны использовать дополнительные методы проверки / удаления, такие как in.hasNext() с in.next(), Проверьте Scanner API.

3: binarySearch(String[], String) метод использует String.compareTo(String), Это определяет лексикографическое упорядочение этого String к параметру String, Попытка сравнить верхний регистр с нижним регистром может не дать ожидаемого результата, так как "the".compareTo("The") не приведет к 0, Вы должны проверить String API для параметров, чтобы либо принудительно вводить все ваши данные в одном случае, возможно, при чтении файла, либо использовать другой вариант сравнения с методом.

4: последнее, что я вижу, может считаться чем-то вроде углового случая, однако с достаточно большим String массив, и строка поиска, которая может находиться далеко в правой части, т.е. сторона высокого индекса, из массива вы можете получить ArrayIndexOutOfBoundsException, Это потому что (low + high) может привести к отрицательному значению, когда результат "должен" быть больше, чем Integer.MAX_VALUE, Затем результат делится на два и все равно дает отрицательное значение. Это может быть решено путем сдвига битов результата вместо деления на 2, (low + high) >>> 1, У Джошуа Блоха есть отличная статья об этом распространенном недостатке в алгоритмах разделяй и властвуй.

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