【问题标题】:implementing a patricia trie in java在java中实现patricia trie
【发布时间】:2012-10-18 04:07:01
【问题描述】:

我正在尝试用 java 重写一个 c++ patricia trie。 c++代码来自here

full source code

我有点卡住了。

这是我的理解:

#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 字符(不完全是 n/8,因为向右移动会将低于 8 的任何内容删除为零)然后我们移动 bit_stream 的值[n>>3] by 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);
}

现在这是令人困惑的地方,第一部分直到第二个 while 循环看起来足够清晰,循环并检查有多少位相等且非零,但我不确定第二个循环在做什么,我们获取两个键的地址并检查它们是否相等,如果它们相等,我们再次检查直到我们发现不相等的位?

主要是我不确定密钥的地址是如何在这里使用的,但我也可能对 bit_get 类中的位移感到困惑。

我想对我的 java 类的 c++ 和 java 中的 trie 进行比较,并且我希望使实现尽可能相似。

【问题讨论】:

标签: java c++ trie radix


【解决方案1】:

我不熟悉这个数据结构,但是你对这段代码的理解有些问题。

首先,calloc 分配 256 个字节,而不是位。 new byte[256] 在 java 中可以比较。

第二,n &amp; 0x7 得到三个位 n,而不是七个。更清晰的写法是n/8n%8 而不是n&gt;&gt;3n &amp; 7,但是如果你的编译器很笨,按位运算可能会稍微快一些。

(bit_stream[n&gt;&gt;3]&gt;&gt;k) &amp; 1 是一样的。

现在,bit_first_different 中的第一个循环循环的是字节,而不是位。检查 0 是为了防止超出键的末端。一旦该循环终止,n 将引用第一个不同的字节。然后第二个循环寻找不同的位。

请注意,如果两个键不同,则第二个循环可能会超出键的末尾,从而可能导致分段错误。

现在,& 正在使用k1[n] 的地址,因为bit_get 函数需要一个指向字符的指针……这会传入比特流的nth 元素。循环后dk[n]的第一个不同位的偏移量。

最后,代码将n(哪个字节?)与d(那个字节中的哪个位?)结合起来给出位。为了清楚起见,我再次提倡8*n+d,但这只是个人喜好问题。

【讨论】:

  • patricia tree 是一个特里树变体。 bit_first_different 函数可能用于在插入和查找过程中查找键从树上掉下来的位置。
  • 即使假设这两个键不同,我至少会添加一个说明前提条件的注释。
【解决方案2】:

我可以用java中的char数组来实现吗?

我的 java 有点生疏,但我相信 char 已在 java 中签名,这意味着 &gt;&gt; 不会按照您的预期行事。这是因为移动有符号数不会移动符号位,所以您真正想要的是 &gt;&gt;&gt; 运算符,或者只使用无符号的 byte 类型。我感觉这是各种错误,所以请仔细检查。

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

在 C 或 C++ 中,*(array + k) 只是编写 array[k] 的另一种方式,因此您的翻译看起来正确。至于解释,bit_stream[n&gt;&gt;3] 本质上是获取所需位所在的字节。 &gt;&gt; k 将所需位移动到最低有效位位置。最后,我们用&amp; 0x1 屏蔽掉所有我们不感兴趣的位。根据该位是否已设置,这会给我们留下 0 或 1 的值。

最终函数所做的是比较 2 个位字符串并返回 2 个字符串首先不同的位位置。第一个循环本质上是第二个循环的优化版本,它不是逐位比较,而是检查整个字节。

换句话说,它首先遍历每个字节并找到前 2 个不同的字节。然后它获取这 2 个不同的字节并循环它们,直到找到不同的前 2 位。请注意,bit_get 函数在这种情况下永远不会收到大于 7 的 n,因为我们知道字节中的某处存在差异。然后根据两个循环的结果构造最终的位位置,如下所示:(number_of_equal_bytes * 8) + number_of_equal_bits)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多