目录
2.1创建一个串对应的路2.2word这个单词之前加入过几次2.3在所有加入字符串中,有多少个是以pre作为前缀的2.4删除单词
1.前缀树的结点定义
#include<iostream>
#include<string>
#include<unordered_set>
using namespace std;
//前缀树的结点定义
class TrieNode {
public:
int pass;//在创建的过程中经过的路的次数
int end;//每条字符串结尾的路的次数
TrieNode* *nexts;
TrieNode(){
pass = 0;
end = 0;
*nexts = new TrieNode[26];
}
TrieNode(int ps, int en) {
pass = ps;
end = en;
//nexts[0]==NULL表示没有走向‘a'的路
//nexts[0]!=NULL表示有走向‘a'的路
//nexts[25]==NULL表示没有走向‘z’的路
//nexts[25]!=NULL表示没有走向‘z’的路
*nexts = new TrieNode[26];
}
};
2.前缀树封装的一些方法
2.1创建一个串对应的路
2.2word这个单词之前加入过几次
2.3在所有加入字符串中,有多少个是以pre作为前缀的
2.4删除单词
class Trie {
private:
TrieNode* root;//头结点
public:
Trie(){
root = new TrieNode;
}
//创建一个串对应的路
void insert(string word) {
if (word.size()<1)
return;
TrieNode* node = root;
node->pass++;//只要经过就+1
int index = 0;
for (char ch : word) {//从左往右遍历字符
index = ch - 'a';//由字符对应哪条路
if (node->nexts[index] == NULL)//没有,就新建一个结点
node->nexts[index] = new TrieNode;
node = node->nexts[index];
node->pass++;
}
node->end++;
}
//word这个单词之前加入过几次
int search(string word) {
TrieNode* node = root;
int index = 0;
for (char ch : word) {
index = ch - 'a';
if (node->nexts[index] == NULL)
return 0;
node = node->nexts[index];
}
return node->end;
}
//在所有加入字符串中,有多少个是以pre作为前缀的
int prefixNumber(string pre) {
TrieNode* node = root;
int index = 0;
for (char ch : pre) {
index = ch - 'a';
if (node->nexts[index] == NULL)
return 0;
node = node->nexts[index];
}
return node->pass;
}
//删除单词
/*
step: 1)先检查是否存在单词,存在了再删,否则直接跳过
2)将单词路过的字符的pass--,到单词末尾再将end--。
*/
void deleteWord(string word) {
if (search(word) != 0) {//先判断是否存在
TrieNode* node = root;
node->pass--;
int index = 0;
TrieNode* a = new TrieNode;
int deleteIndex = -1;
unordered_set< TrieNode*>deleteSet;
for (int i = 0;i<word.size();i++) {
index = word[i] - 'a';
//如果pass为0了,就将头结点记录一下,放在表中,最后释放
if (--node->nexts[index]->pass == 0) {
//如果为不为空就说明之前已经设置过了,就直接用原来的值就行
a = a == NULL ? node : a;
deleteIndex = deleteIndex == -1 ? index : deleteIndex;
deleteSet.insert(node->nexts[index]);
}
node = node->nexts[index];
}
node->end--;
a->nexts[deleteIndex] = NULL;
//析构释放
for (TrieNode* dele : deleteSet) {
delete dele;
dele = NULL;
}
}
}
};