我想插入一个字符串并使用trie数据结构进行搜索操作。这是我使用指针的第一个实现,所以我真的很困惑我在代码中做错了,它给出了编译错误。请帮助调试请告诉我指针逻辑有什么问题。
typedef struct trie {
unordered_multimap<char, struct trie> child;
bool isEnd;
} trie;
trie* newtrienode()
{
trie* newnode = (trie*)malloc(sizeof(trie));
newnode->isEnd = false;
return newnode;
}
trie* root = newtrienode();
void insert(string word)
{
trie* current = root;
for (int i = 0; i < word.length(); i++) {
char ch = word[i];
trie* node = current->child[ch];
if (node == NULL) {
trie* node = newtrienode();
current->child.insert(pair<char, trie>(ch, node));
}
current = node;
}
current->isEnd = true;
}
bool search(string word)
{
trie* current = root;
for (int i = 0; i < word.length(); i++) {
char ch = word[i];
trie* node = current->child[ch];
if (node == NULL) {
return false;
}
current = node;
}
return true;
}
答案 0 :(得分:0)
除了评论中提到的内容外,我发现代码存在一些问题。
1
trie* newnode = (trie*)malloc(sizeof(trie));
这不会创建trie
类型的对象,它只会分配大小为trie
的内存块,并将指针指向变量newnode
。特别是,它不会调用unordered_multimap
的构造函数。通过该指针访问child
成员会产生未定义的行为。此外,你永远不会释放那段记忆。
2
typedef struct trie {
unordered_multimap<char, struct trie> child;
bool isEnd;
} trie;
在第二行,您声明一个unordered_multimap
数据成员,其类型不完整trie
作为第二个模板参数。有些编译器允许这样做,但标准并不要求它们。另一方面,shared_ptr
需要使用不完整类型作为模板参数。此外,一个节点每个字符只能有一个子树,因此您不需要多个映射;一张地图就足够了。因此,我建议使用unordered_map<char, shared_ptr<trie>>
并将所有trie*
替换为shared_ptr<trie>
。在释放root
后,它还会处理删除对象。
newtrienode()
函数将如下所示:
shared_ptr<trie> newtrienode()
{
shared_ptr<trie> newnode (new trie());
newnode->isEnd = false;
return newnode;
}
3
trie* node = current->child[ch];
if (node == NULL) {
当密钥不存在时, operator[]
不会返回NULL
。它将默认构造的对象插入容器并返回对它的引用。要检查密钥是否存在,请使用find
或count
。
4
trie* node = current->child[ch];
if (node == NULL) {
trie* node = newtrienode();
current->child.insert(pair<char, trie>(ch, node));
}
current = node;
请注意,在第三行中您要声明一个新变量。在第一行声明的变量node
不会被更改。