【问题标题】:StackOverflowError in recursive binary search in file in javajava中文件中递归二进制搜索中的StackOverflowError
【发布时间】:2013-01-18 03:54:13
【问题描述】:

filepointer 卡在导致StackOverflowError 的点。你能指出我这里到底出了什么问题吗?确切的错误是:java.lang.StackOverflowError

我正在寻找位置,因为记录宽度不固定。

这是一段代码:

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.StackOverflowError 中的异常

>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)

【问题讨论】:

  • Stackoverflow 错误是当您遇到无限循环或条件并且程序无法为其分配更多内存到堆栈上时。
  • 试试调试器。或者为更小的功能编写小测试。在目前的形式中,问题“过于本地化”
  • 异常的堆栈跟踪是什么?
  • @AlexKreutznaer :添加了堆栈跟踪
  • 哦,知道了。无法给出整个堆栈跟踪 - 它没有尽头。

标签: java recursion stack-overflow binary-search random-access


【解决方案1】:
else if(compared > 0)
    binarySearch(raf,searchvalue,mreal,high);

那应该是 mreal + 1。

此外,递归对于二分搜索来说是多余的......通常循环更快。

罗尔夫

编辑:====

好的,所以它仍然不起作用。这是因为我只说对了一部分。我只看了一会儿代码,发现了问题,但后来我用错误的值修复了它。

您应该添加与比较的字符串中的字符数以及行终止符(如果有 - 它可能是最后一行...),而不是添加 1。

整件事告诉我的是,这可能是家庭作业......以及递归练习和二分搜索研究。

不为你做功课,我会花一点时间批评你的代码。

二分查找应该是找到中点,如果中点匹配,则返回,如果大于搜索,则在中点之前搜索,否则在中点之后搜索。

您的代码正在获取中点“正确”和“之前”正确,但它没有搜索“之后”...因为您没有正确计算“之后”部分..您需要“在整个字符串之后,而不仅仅是在第一个字符之后。修理它。请记住,使用 readLine() 意味着您不知道行终止符(是 '\r\n' 还是只是 '\n'?)。我建议在“中间”点之后使用一个循环,然后自己向前走,直到到达另一个 \n,然后在需要时使用该 (+1) 来计算“之后”搜索的位置。

其他一些cmets....

  • 不要使用“自动装箱”。使用 long 基元而不是 Long 对象。
  • 当 getFilePointer() 返回的值在变量“filepointer”中已知时,为什么还要调用它。
  • 计算'中间'时,使用低+高>>> 1 ....它会给你的讲师留下深刻印象,你可以说你知道为什么读完这篇文章:http://googleresearch.blogspot.ca/2006/06/extra-extra-read-all-about-it-nearly.html
  • 当您阅读该内容时,您会明白为什么在循环中进行二分搜索比在递归中进行更好。
  • 如果您确实使用递归,则应将参数设置为“final”,因为这样会在堆栈上留下更小的足迹,并且可以“更深”。
  • 如果您确实使用递归,那么您应该最小化您在方法中创建的对象...例如 StringBuilders...。

罗尔夫

【讨论】:

  • 我刚改了。但同样的问题。
  • 一个快速的问题:当我执行 str = raf.readLine(); 时,在此语句之后,文件指针指向哪里?当前行的结尾还是新行的开头?
  • 好问题。该文档没有强调一种或另一种方式。尽管文件指针将指向第一个字符 after 行终止符(因此下一个 readLine() 将起作用),但这是有道理的。
猜你喜欢
  • 2021-04-20
  • 2022-08-02
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
相关资源
最近更新 更多