所以我有这段代码(这不是我的),我无法理解这些结构的样子。有人可以解释一下吗?
typedef struct trie_node trie_node_t;
struct trie_node
{
int value;
trie_node_t *children[ALPHABET_SIZE];
};
// trie ADT
typedef struct trie trie_t;
struct trie
{
trie_node_t *root;
int count;
};
第二个结构中的Int计数用于计算放在树中的所有单词,但我想知道每个单词放在那里多少次,除了修改其余代码之外,我应该如何修改结构实现这个目标?
答案 0 :(得分:1)
我想你熟悉trie的概念,你可以通过步行(或爬行,使用链接代码的单词)在树的下方找到单词的字和前缀,并带有单词的字母和分支。每个节点根据您找到的字母。每个节点都有很多孩子; 26如果你使用不区分大小写的拉丁字母。
这个词是在你到达那里的路径中编码的:
root->[f]->[i]->[s]->[h] --> "fish"
现在您需要知道当前节点是否代表一个单词。 "fish"
是一个单词,但"fis"
不是。您不能使用节点是没有子节点的叶子这一事实,因为"fishbone"
可能在字典中。这就是value
条目的用途:零表示当前节点不表示单词,否则该值是当前单词的从1开始的索引。
当你创建一个新条目时,你只需要向下爬行trie,可能会在你去的时候创建新节点,并用当前计数单词作为值来标记最后一个节点。如果"fishbode"
已经在特里,并且您添加"fish"
,则不会创建新节点,只会使用新值标记"h"
节点。
trie
结构只是包含trie的根节点和计数的帮助器。
如果要跟踪发生的事件,请在节点中添加count
字段,并在设置value
时将其递增。 (原始代码不会检查某个值是否已经在trie中,并且无条件地添加单词,从而覆盖任何旧值。)
您还可以通过拥有prefix_count
字段来保留当前节点上以前缀开头的所有单词的计数,并在插入密钥时传递节点时将其递增。
当您想要检索发生时,您必须遍历所有子树。
尝试对于从用户输入的第一个字母或T9风格的打字系统中自动扩展单词非常有用,但它们更像是内存贪婪。如果你只是想计算单词的出现次数(不使用trie的好处),那么使用单个哈希映射字来计算它可能更容易。