C 节省空间的trie

C 节省空间的trie,c,data-structures,trie,C,Data Structures,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]; }; 当我添加一个节点时,它的索引是该字符的无符号字符转换。例如,如果我想添加“c”,那么 是指向新添加节点的指针。但是,这个实现需要声明一个包含256个元素的node*

我正在尝试在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];
};
当我添加一个节点时,它的索引是该字符的无符号字符转换。例如,如果我想添加“c”,那么

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

struct node** children;
然后在添加节点时,只需为节点分配malloc空间并

children[(unsigned char)'c']
指向新节点。问题是,如果我不先为孩子们定义malloc空间,那么我显然不能引用任何索引,否则这是一个很大的错误


所以我的问题是:如何实现trie,使其只存储指向其子节点的非空指针?

您可以尝试使用,其中每个节点只有一个子指针,每个节点也有指向“同级”的指针,因此,所有同级都有效地存储为一个链表,而不是由父节点直接指向。

您不可能同时使用两种方式,既节省空间又在子节点中进行O(1)查找

当您只为实际添加的条目分配空间,而不是为空指针分配空间时,您就不能再这样做了

children[(unsigned char)'c']
因为您不能再直接索引到数组中

另一种方法是简单地对子对象进行线性搜索。并存储
子项
数组有多少个条目的额外计数,即

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] = ...;
(i=0;i{ 如果(子项[i]=“c”) 打破 } 如果(i==len){ //…为子项中的一项重新分配和添加空间 } 儿童[我]=。。。;
如果您的树在一个级别上有很多非空条目,您可以按排序顺序插入子项并进行二进制搜索。或者您可以将孩子添加为链表而不是数组。

如果您只想进行英文关键字搜索,我认为您可以将孩子的大小最小化,从256个减少到26个,刚好可以覆盖26个字母a-z

此外,您可以使用链表来保持子对象的数量更小,这样我们就可以进行更有效的迭代


我还没有浏览过这些库,但我认为会有所帮助。

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

我还必须补充一点,如果您正在使用的字符集接近无界,那么有一个节点的链接列表可能就可以了。如果你喜欢一个难以管理的噩梦,你可以选择一种混合的方法,在这种方法中,前几个级别将它们的子级保存在哈希表中,而较低级别有它们的链接列表。对于一个真正的bug农场,选择一个动态的,当每个链接列表通过一个阈值时,您可以动态地将其转换为哈希表。你可以很容易地分摊成本


可能性是无穷的

为什么不检查
children
是否为空?您是否考虑过有向无环词图?看到了吗?这不是破坏了遍历时间吗?@kyun是的,但正如另一位回答者所指出的,你不能既节省空间又有很好的遍历时间。如果速度是一个问题,a可能是一个不错的选择(每个节点都有3个指针:一个指向“较小”的兄弟节点,一个指向“较大”的兄弟节点,一个指向子节点)。很好,我知道这可以更快
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] = ...;