我正在尝试在java中重写c ++ patricia trie。 c ++代码来自here
我有点卡住了。
所以这是我的理解:
#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到0的任何值)然后我们移动bit_stream的值[n>&gt; 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);
}
现在这是令人困惑的地方,第一部分直到第二部分while循环看起来足够清楚,循环并检查多少位相等且非零,但我不确定第二循环在做什么,我们取两个键的地址并检查它们是否相等的第一位,如果它们是我们再次检查,直到找到不相等的位?
主要是我不确定如何在这里使用密钥的地址,但我也可能对bit_get类中的位移位感到困惑。
我想在c ++和java中为我的java类进行比较,我希望尽可能保持类似的实现。
答案 0 :(得分:2)
我不熟悉这种数据结构,但是您对此代码的理解存在一些问题。
首先,calloc
分配256个字节,而不是位。 new byte[256]
在java中具有可比性。
其次,n & 0x7
得到三位n
,而不是七位。更清楚的方法是n/8
和n%8
而不是n>>3
和n & 7
,但如果你的编译器是愚蠢的,那么按位运算可能会稍快一些。
(bit_stream[n>>3]>>k) & 1
是一样的。
现在,bit_first_different
中的第一个循环遍历字节,而不是位。检查0是为了防止关闭键的结束。一旦该循环终止,n
指的是第一个不同的字节。然后第二个循环寻找哪个位不同。
请注意,如果两个键没有区别,那么第二个循环可能会在键的末尾运行,可能会导致分段错误。
现在,&amp;取k1[n]
的地址,因为bit_get
函数期望指向字符的指针...这会传递位流的n
元素。在循环之后,d
是k[n]
的第一个不同位的偏移量。
最后,代码将n
(哪个字节?)与d
(该字节中的哪个位?)组合在一起。我再次主张8*n+d
以澄清,但这只是一种品味问题。
答案 1 :(得分:0)
我可以在java中用char数组实现吗?
我的java有点生疏,但我相信char
已在java中签名,这意味着>>
将无法达到您的预期。那是因为移位带符号的数字不会改变符号位,所以你真正想要的是>>>
运算符,或者只使用无符号的byte
类型。我有一种感觉,这是各种错误所以请仔细检查。
return(bit_stream [n>&gt;&gt; 3]&gt;&gt; k)&amp;为0x1;
在C或C ++中,*(array + k)
只是另一种写array[k]
的方式,因此您的翻译看起来是正确的。至于解释,bit_stream[n>>3]
基本上取出了所需位所在的字节。 >> k
在最低有效位位置移动所需位。最后,我们通过使用& 0x1
屏蔽它们来删除我们不感兴趣的所有位。这给我们留下0或1的值,具体取决于该位是否已设置。
最终函数的作用是比较2位字符串并返回2个字符串首先不同的位位置。第一个循环本质上是第二个循环的优化版本,而不是逐位比较,而是检查整个字节。
换句话说,它首先遍历每个字节并找到不同的前两个字节。然后它获取这2个不同的字节并循环它们,直到它找到不同的前2位。请注意,在这种情况下,bit_get
函数永远不会收到大于7的n,因为我们知道字节中的某处存在差异。然后根据两个循环的结果构造最终的位位置,如:(number_of_equal_bytes * 8) + number_of_equal_bits)
。