繁体   English   中英

节省空间的特里

[英]Space efficient trie

我正在尝试在C中实现一个节省空间的trie。这是我的结构:

struct node {
char val; //character stored in node
int key; //key value if this character is an end of word
struct node* children[256];
};

当我添加一个节点时,它的索引是该字符的unsigned char cast。 例如,如果我想添加“c”,那么

children[(unsigned char)'c']

是指向新添加节点的指针。 但是,这个实现要求我声明一个256个元素的节点*数组。 我想做的是:

struct node** children;

然后在添加节点时,只需要为节点提供malloc空间即可

children[(unsigned char)'c']

指向新节点。 问题是,如果我先没有为孩子们提供malloc空间,那么我显然无法引用任何索引,否则这是一个很大的错误。

所以我的问题是:我如何实现一个trie,它只存储非子指针给它的子节点?

您可以尝试使用de la Briandais trie ,其中每个节点只有一个子指针,并且每个节点还有一个指向“兄弟”的指针,因此所有兄弟节点都有效地存储为链接列表而不是直接指向由父母。

你无法真正拥有它,并且既节省空间又在子节点中进行O(1)查找。

如果只为实际添加的条目分配空间,而不是空指针,则不能再这样做

children[(unsigned char)'c']

因为您无法再直接索引到数组中。

另一种方法是简单地通过孩子进行线性搜索。 并存储children数组具有多少条目的附加计数

children[(unsigned char)'c'] = ...;

必须成为

for(i = 0; i < len; i++) {
  if(children[i] == 'c')
     break;
} 
if(i == len) {
  //...reallocate and add space for one item in children
}
children[i] = ...;

如果您的树在一个级别上有很多非空条目,您可以按排序顺序插入子项并进行二分查找。 或者您可以将子项添加为链接列表而不是数组。

通过使每个节点的子节点成为节点的哈希表,您可以节省空间并保持恒定的查找时间。 特别是当涉及到Unicode字符时,字典中可以包含的字符集不限于52 +,这更像是一种要求,而不是一种精确的要求。 通过这种方式,您可以保持使用trie的优势,同时节省时间和空间。

我还必须补充一点,如果您使用的字符集接近无限制,则可能只有一个链接的节点列表可以正常工作。 如果你喜欢无法控制的噩梦,你可以选择混合方法,其中前几个级别将他们的孩子保留在哈希表中,而较低级别有一个链表。 对于真正的错误服务器场,请选择动态服务器场,当每个链接列表超过阈值时,您可以将其转换为动态哈希表。 您可以轻松摊还成本。

可能性无穷无尽!

如果您只想进行英语关键词搜索,我认为您可以将孩子的大小从256减少到26,这足以覆盖26个字母az。

此外,您可以使用链接列表来保持子项数量更小,以便我们可以进行更有效的迭代。

我还没有浏览过图书馆,但我认为实施将有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM