0

がある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)
4

1 に答える 1

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

それはmreal + 1でなければなりません。

また、再帰は二分探索ではやり過ぎです....通常、ループの方が高速です。

ロルフ

編集:====

OK、まだ動作しません。それは、私が部分的にしか正しかったからです。ちょっとだけコードを見て問題に気づきましたが、間違った値で修正しました。

1 を追加する代わりに、比較した文字列の文字数に加えて、行末 (もしあれば - 最後の行かもしれません...) を追加する必要があります。

このすべてが私に教えてくれるのは、これはおそらく宿題だということです...そして再帰の練習と二分探索の研究です。

あなたのために宿題をすることなく、私はあなたのコードを批判するのに少し時間を費やします.

二分探索は中間点を見つけて、中間点が一致する場合はそれを返し、それが検索よりも大きい場合は中間点の前を検索し、そうでない場合は中間点を検索します。

あなたのコードは中間点を「正しく」、「前」を正しく取得していますが、「後」を検索していません...「後」の部分を正しく計算していないためです..「後」である必要があります最初の文字の直後ではなく、文字列全体。修理する。readLine() を使用すると、行末記号がわからないことを意味します ('\r\n' なのか、単に '\n' なのか?)。「中間」ポイントの後にループを使用し、別の \n に到達するまで自分自身を歩き、必要に応じて「後」検索の位置を計算するためにその (+1) を使用することをお勧めします。

他のコメントをいくつか....

  • 「オートボクシング」を使用しないでください。Long オブジェクトの代わりに long プリミティブを使用します。
  • getFilePointer() が返す値が変数 'filepointer' で既にわかっている場合に、なぜ getFilePointer() を呼び出すのですか。
  • 「中間」を計算するときは、低 + 高 >>> 1 を使用してください。これは講師の印象に残り、これを読めばその理由がわかると言えます: http://googleresearch.blogspot.ca/2006/06/ extra-extra-read-all-about-it-nearly.html
  • これを読んでいるうちに、再帰で実行するよりもループで二分探索を実行するほうが優れている理由がわかります。
  • 再帰を使用する場合、パラメーターを「最終」に設定する必要があります。これにより、スタックのフットプリントが小さくなり、「より深く」進むことができます。
  • 再帰を使用する場合、メソッドで作成するオブジェクトを最小限に抑える必要があります... StringBuilders のように....

ロルフ

于 2013-01-18T04:52:22.780 に答える