二进制搜索帮助:将文件读入数组,查找特定行

时间:2014-05-08 03:28:51

标签: java arrays binary-search

在文件中,每个条目将包含两行;第一行是数字,第二行是标题。文件中的条目将按数字升序排列。

创建一个将文件读入数组的程序。然后,用户将根据号码请求标题。您的程序将执行二进制搜索以查找标题。

目前,我将文件中的所有内容读入arrayList,然后将其转换为数组。

我的第一个主要问题是我的二分查找方法似乎没有起作用;我试图搜索一个数字,它只是返回false。其次,即使这设法工作,我不确定如何记录文本文件中找到结果的哪一行。我认为这是必要的,因为我必须输出后面的行。这是文本文件的示例。

2

救世主戏剧

4

晚祷[/ p>

7

在迫害下的善良祷告

等。这是我目前的代码

package Psalms;

import java.io.*;

import javax.swing.*;

import java.util.ArrayList;

import java.util.List;

public class Psalms {



public static void main(String[] args) throws IOException {
    // Creates array list. Reads lines into it
    List<String> psalms = new ArrayList<String>();
    BufferedReader readFile = new BufferedReader(new FileReader("Psalms.txt"));
    String line;
    while ((line = readFile.readLine()) != null) {
        psalms.add(line);
    }
   readFile.close();

    String[] psalmArray = new String[psalms.size()];
    psalmArray = psalms.toArray(psalmArray);

    //Asks user what to search for.
    String psalmSearch = (JOptionPane.showInputDialog("What number Psalm would you like to search for?"));
    System.out.println("Binary Search: " + psalmSearch + " " + binarySearch(
            psalmArray, 0, psalmArray.length - 1, psalmSearch));

}

public static boolean binarySearch(String myArray[], int left,
        int right, String searchForPsalm) {
    int middle;

    if (left > right) {
        return false;
    }
    middle = (left + right) / 2;
    if (myArray[middle].equals(searchForPsalm)) {
        return true;
    }
    if (searchForPsalm.compareTo(myArray[middle]) < 0) {
        return binarySearch(myArray, left, middle - 1,
                searchForPsalm);
    } else {
        return binarySearch(myArray, middle + 1, right,
                searchForPsalm);
    }
}

}

2 个答案:

答案 0 :(得分:0)

现在,您正在做的是在文件中每行添加一个String到List。因此,此列表将如下所示:

<"2", "The messianic drama", "4", "Evening prayer", "7">

问题在于,当您尝试对此执行二进制搜索时,您将一些字符串与标题进行比较,而一些字符串与数字进行比较。

这是我推荐的方法,假设您获得的文件已经排序:

在阅读文件的行时,在将它们添加到两个不同的列表之间交替,其中一个包含标题,另一个包含整数。从文件中添加数字时,请确保使用Integer.parseInt(String)将其转换为整数。想法是创建两个这样的列表:

Title List = <"The messianic drama", "evening prayer", "Prayer of the virtuous under 
persecution">
Tile Number List: <2,4,7>

你是否看到2在列表中的同一个索引与另一个中的The messianic drama相同?

然后,当您执行二进制搜索以查找标题编号时,如果找到要查找的编号,则只需返回标题列表中相同位置的字符串。

如果您的标题没有在文件中按顺序编号,您可能需要考虑制作StringInteger的元组。这有点复杂,因为你必须创建一个类并实现一个Comparator,这样你就可以正确地对它们进行排序。

答案 1 :(得分:0)

假设您的文件已正确验证(即每个诗篇编号后跟一个文本行),那么对于现有的binarySearch方法,需要进行2次更正:

    .
    .
    middle = (left + right) / 2;
    middle += middle & 1;  // to the nearest even number
    .
    .
    .
    } else {
        return binarySearch(myArray, middle + 2, right,
                searchForPsalm);
    }
}

1)由于所有诗篇数字都在偶数数组位置,你需要确保将中间数设置为最接近的偶数偏移量。

2)对于“右侧”分区,您应跳过文本行,将其设置为“mid + 2”。

这将确保您按照预期比较诗篇编号。

现在不是返回布尔值,而是返回字符串以显示相关文本(如果找到),所以这是修改后的方法:

public static String  binarySearch(String myArray[], int left,
        int right, String searchForPsalm) {
    int middle;

    if (left > right) {
        return "";
    }
    middle = (left + right) / 2;
    middle += middle & 1;
    if (myArray[middle].equals(searchForPsalm)) {
        return myArray[middle + 1];
    }
    if (searchForPsalm.compareTo(myArray[middle]) < 0) {
        return binarySearch(myArray, left, middle - 1,
                searchForPsalm);
    } else {
        return binarySearch(myArray, middle + 2, right,
                searchForPsalm);
    }
}

如果没有找到条目,它将返回一个空字符串。

此外,如果你还需要返回'middle'值,你可以修改它以返回一个对象,比如Result,它有'中间'和字符串值 - 参见这里的例子:

How to return multiple values in java?