【发布时间】:2020-04-28 00:40:02
【问题描述】:
我想使用一个向量来实现一个 trie 来存储节点,但不知何故我的插入方法不起作用。我已经设法使用不同的实现来构建 trie 数据结构,但我想了解为什么我当前的实现不起作用。
作品(不是基于索引的子/引用存储):
struct Trie {
struct Trie *references[26];
bool end; //It is true if node represents end of word.
};
不起作用(基于索引的子/引用存储):
struct node {
int references[26] = {0};
bool end;
};
由于插入功能错误,它不起作用。
void insert_word(string s){
node *current_node = &trie[0];
// current_node->references[4] = 9999 WORKS! Node in Trie is UPDATED
for(int i=0;i<s.size();i++){
print_trie();
int letter_num = static_cast<int>(tolower(s[i])) - static_cast<int>('a');
int next_index = current_node->references[letter_num];
cout << "letter num: " << letter_num << " next index: " << next_index << endl;
if(next_index == 0){
node new_node;
trie.push_back(new_node);
current_node->references[letter_num] = trie.size()-1; // DOESN'T WORK! Node in Trie is NOT UPDATED
cout << "new value: ";
for(auto c:current_node->references)
cout << c << " ";
cout << endl;
cout << "in for" << endl;
print_trie();
current_node = &trie.back();
} else{
current_node = &trie[next_index];
}
}
current_node->end = true;
}
问题在于,当我访问current_node 作为对对象 ob 的引用时,我会更改它的值。 trie 向量中的对象/节点并不总是更新。它在第二行工作,但更进一步它以某种方式停止工作。我想知道为什么。
这是我为简化问题而编写的一个简短的调试程序。这里似乎一切正常。
n1.references[0] = 1;
n2.references[0] = 2;
n3.references[0] = 3;
trie.push_back(n1);
trie.push_back(n2);
trie.push_back(n3);
node *n = &trie[0];
n->references[0] = 10; // Tree is updated properly
n = &trie[1];
n->references[0] = 11; // Tree is updated properly
你能帮我理解为什么插入功能不能正常工作吗?
编辑:最小的工作示例
#include <vector>
#include <string>
#include <iostream>
using namespace std;
struct node
{
int num_words;
int references [26] = {0};
bool end;
};
vector<node> trie;
int n;
void print_trie(){
cout << "#### NEW PRINT TRIE ##### " << endl;
for(int i=0;i<trie.size();i++){
cout << "node " << i << ": ";
for(int j=0;j<26;j++)
cout << trie[i].references[j] << " ";
cout << endl;
}
}
void insert_word(string s){
node *current_node = &trie[0];
// current_node->references[4] = 9999 WORKS! Node in Trie is UPDATED
for(int i=0;i<s.size();i++){
print_trie();
int letter_num = static_cast<int>(tolower(s[i])) - static_cast<int>('a');
int next_index = current_node->references[letter_num];
cout << "letter num: " << letter_num << " next index: " << next_index << endl;
if(next_index == 0){
node new_node;
trie.push_back(new_node);
current_node->references[letter_num] = trie.size()-1; // DOESN'T WORK! Node in Trie is NOT UPDATED
cout << "new reference value of node: ";
for(auto c:current_node->references)
cout << c << " ";
cout << endl;
current_node = &(trie[trie.size()-1]);
} else{
current_node = &trie[next_index];
}
}
current_node->end = true;
}
int main()
{
node root;
trie.push_back(root);
insert_word("hallohallo");
return 0;
}
【问题讨论】:
-
这些:
node *current_node = &trie[0];和current_node = &trie.back();和current_node = &trie[next_index]是引入悬空指针的秘诀。看循环操作。当/如果向量由于push_back操作(显然在您的循环中)而调整大小时,这些指针存储可能/将变得无效。口头禅:不要将指向对象的指针存储在经历可变大小操作的向量中;使用 index 代替。
标签: c++ pointers reference trie