关于前缀树的内容最好看看视频了解逻辑结构,然后代码实现一下
前缀树是一种树形数据结构,广泛用于字符串查找,思想上类似哈希。在字符串查找上有非常好的效果,但是消耗空间较大,下面给出前缀树的c++实现
#ifndef TRIE_H_INCLUDED #define TRIE_H_INCLUDED #includeusing namespace std; //假设字符串都是小写字母 typedef struct TrieNode { int pass = 0; //有几个字符串经过此结点(前缀包含这个字符的字符串数量) int end = 0; //以此结点结束的字符串的数量,如果不允许重复插入,可以改成bool TrieNode* next[26]{nullptr}; //26个空位,准备挂下一结点a-z ,没有时置为nullptr }TrieNode ; //前缀树结点定义 //前缀树 class Trie { public: TrieNode *root = nullptr; //根节点 Trie() { root = new TrieNode(); //构造函数初始化root } ~Trie() { deletememory(root); //析构释放空间 } void insert(string word) { TrieNode *temp = root; temp->pass++; //根节点的pass代表树上有多少字符串以空字符串为前缀,也就是字符串总数 for(unsigned int i = 0 ;i next[word[i]-'a'] == nullptr) //如果先前没有字符串经过此结点 temp->next[word[i]-'a'] = new TrieNode(); //建出新结点 temp = temp->next[word[i]-'a']; temp->pass++; } temp->end++; //temp指向字符串最后一个结点,end++表示多了一个字符串以此结点结尾 } bool search(string word) { TrieNode *temp = root; for(char c : word) //遍历字符串每个字符,也可以使用for i~word.size写法 { if(temp->next[c-'a'] == nullptr ) //找的过程发现没路了,false return false; temp = temp->next[c-'a']; } return temp->end; } bool startsWith(string prefix) { TrieNode *temp = root; for(unsigned int i = 0 ;i next[prefix[i]-'a'] == nullptr) return false; temp = temp->next[prefix[i]-'a']; } return true; } void deletememory( TrieNode *temp) { for(int i = 0 ;i < 26; i++) //对一个结点,将其next数组存放的后续节点全部释放 if(temp->next[i]) deletememory(temp->next[i]); delete temp; //释放本结点空间 } void remove(string word) { if(true == search(word)) //树上有这个字符串才需要删除 { TrieNode *temp = root; temp->pass--; for(unsigned int i = 0 ; i< word.size() ;i++) { if( --temp->next[word[i]-'a']->pass == 0) //唯一经过该结点的字符串被删除 { deletememory(temp->next[word[i]-'a'] ); //递归释放此结点后面路径 temp->next[word[i]-'a'] = nullptr; 结点置nulptr return ; } temp = temp->next[word[i] - 'a']; } temp->end--; //如果字符串所有字符删除后,路径没变,还需要把最后结点end-1 } } }; #endif // TRIE_H_INCLUDED上面所给出的实现要求字符串都是小写字母,但如果字符种类非常多,我们需要将存储下一结点的数据结构进行修改,因为定长数组的方式可能会造成空间巨大的浪费,我们可以使用哈希map的方式存储 <字符,下一结点>



