2

Java で C++ のパトリシア トライを書き直そうとしています。C++コードはこちらから

完全なソース コード

私は少し立ち往生しています。

だからここに私の理解があります:

#define ZEROTAB_SIZE 256
head->key = (char*)calloc(ZEROTAB_SIZE, 1);

キー用に 256 ビットの配列を作成するため、最大長 32 文字の文字列を作成し、すべての文字を 8 ビットで表すことができます。これをJavaのchar配列で実装できますか?

template <class T>
int PatriciaTrie<T>::bit_get(PatriciaTrieKey bit_stream, int n) {
  if (n < 0) return 2; // "pseudo-bit" with a value of 2.
  int k = (n & 0x7);
  return ( (*(bit_stream + (n >> 3))) >> k) & 0x1;
}

k は n の最後の 7 ビットを取得し、文字列の n/8 文字に移動します (右にシフトすると 8 未満のものはすべて削除されてゼロになるため、正確には n/8 ではありません)、bit_stream[n> の値をシフトします。 >3] k によって、最後のビットを取得します。Javaで配列を使用する場合、これを次のように書き換えることができますか

return (bit_stream[n>>3] >> k) & 0x1;

?

template <class T>
int PatriciaTrie<T>::bit_first_different(PatriciaTrieKey k1, PatriciaTrieKey k2) {
    if (!k1 || !k2)
        return 0; // First bit is different!
    int n = 0;
    int d = 0;
    while ( (k1[n] == k2[n]) &&
            (k1[n] != 0) &&
            (k2[n] != 0) )
        n++;
    while (bit_get(&k1[n], d) == bit_get(&k2[n], d))
        d++;
    return ((n << 3) + d);
}

ここがややこしいところです。最初の部分から 2 番目の while ループまでは十分に明確に見えます。ループして、ゼロ以外のビットがいくつあるかを確認しますが、2 番目のループが何をしているのかわかりません。アドレスを取得します。 2つのキーの最初のビットが等しいかどうかをチェックし、等しい場合は、等しくないビットが見つかるまでもう一度チェックしますか?

主に、キーのアドレスがここでどのように使用されているかわかりませんが、bit_get クラスでのビット シフトについても混乱する可能性があります。

JavaクラスのC ++とJavaのトライを比較したいのですが、実装をできるだけ類似させたいと思っています。

4

2 に答える 2

2

私はこのデータ構造に詳しくありませんが、このコードの理解にはいくつかの問題があります。

まず、callocビットではなく 256 バイトを割り当てます。 new byte[256]Javaで匹敵するでしょう。

次に、の7 ビットではなくn & 0x73 ビットを取得します。nこれをより明確に記述する方法はn/8andn%8の代わりにn>>3andn & 7になりますが、コンパイラが愚かな場合、ビット単位の操作はわずかに高速になる可能性があります。

あなたは正しいです、それ(bit_stream[n>>3]>>k) & 1は同じです。

ここで、 の最初のループは、bit_first_differentビットではなくバイトをループします。0 のチェックは、キーの端から外れるのを防ぐためです。そのループが終了したらn、最初の異なるバイトを参照します。2 番目のループは、どのビットが異なるかを探します。

2 つのキーが異なっていない場合、2 番目のループがキーの最後で実行され、セグメンテーション違反が発生する可能性があることに注意してください。

関数が文字へのポインターを期待しているk1[n]ため、 & はのアドレスを取得しています...これは、ビットストリームの th 要素を渡します。ループの後、は の最初の異なるビットのオフセットです。bit_getndk[n]

最後に、コードはn(どのバイト?) とd(そのバイトのどのビット?) を組み合わせてビットを指定します。繰り返し8*n+dますが、明確にすることを主張しますが、それは好みの問題です。

于 2012-10-28T18:51:19.587 に答える
0

これをJavaのchar配列で実装できますか?

私のJavaは少し錆びていますcharが、Javaでサインインされている>>と思います。つまり、期待どおりの動作をしません。これは、符号付き数値をシフトしても符号ビットがシフトされないため、本当に必要なのは>>>演算子であるか、byte符号なしの型を使用するだけだからです。いろいろ間違っている気がしますので、よく確認してください。

return(bit_stream [n >> 3] >> k)&0x1;

CまたはC++では、翻訳が正しく見える*(array + k)ように書くためのもう1つの方法です。array[k]解釈に関しては、bit_stream[n>>3]基本的に、目的のビットが配置されているバイトをフェッチします。>> k目的のビットを最下位ビット位置に移動します。最後に、関心のないすべてのビットを。でマスクして削除します& 0x1。これにより、ビットが設定されているかどうかに応じて、0または1の値が残ります。

最後の関数は、2つのビット文字列を比較し、2つの文字列が最初に異なるビット位置を返します。最初のループは基本的に2番目のループの最適化されたバージョンであり、ビットごとの比較を行う代わりに、バイト全体をチェックします。

つまり、最初にすべてのバイトをループし、異なる最初の2つを見つけます。次に、それらの2つの異なるバイトを取得し、異なる最初の2ビットが見つかるまでそれらをループします。bit_getこのシナリオでは、バイトのどこかに違いがあることがわかっているため、関数がnより大きい7を受け取ることはないことに注意してください。次に、次のように両方のループの結果から最終的なビット位置が作成されます(number_of_equal_bytes * 8) + number_of_equal_bits)

于 2012-10-28T18:43:39.460 に答える