前缀树三个主要的函数:
1.添加word void insert(string word)
2. 查询是否在字典树中 bool search(string word)
3.返回以字符串pre为前缀的单词数量 int prefixNumber(string pre):
用前缀树很重要的一点是可以查找以“pre”,就是某些字母开头的,不然就用哈希表,或者其它的词频统计方式。
直接上代码吧。
//英文字母不区分大小写是26叉树,数字是10叉树
const int MaxNum = 26;
// 数组方式
class TrieNodeArr{
public:
int pass;
int end;
TrieNodeArr* nexts[MaxNum]; //此处为指向下一个Node的指针
TrieNodeArr()
{
pass = 0;
end = 0;
for (int i = 0; i < MaxNum; i++) //构造函数不用new
{
nexts[i] = NULL;
}
//如果字符全是小写 nexts 下级对应的路的位置 a-z 26个字母
//0-a ...25-z
//nexts[0]==NULL;表示没有走向a的路。
//nexts[0]!=NULL;表示有走向a的路。
//...
}
};
//1.root 为指针
class Trietree
{
public:
Trietree();
~Trietree();
TrieNodeArr *root;
void insert(string word);
void myDeleteJAVA(string word);
bool mysearch(string word);
int prefixNumber(string word);
void destory(TrieNodeArr* node);
void myDeleteCPP(string word);
};
Trietree::Trietree()
{
root = new TrieNodeArr();
}
Trietree::~Trietree()
{
destory(root);
}
void Trietree::destory(TrieNodeArr* node)
{
if (node == nullptr)
return;
for (int i = 0; i < MaxNum; i++)
{
destory(node->nexts[i]);
}
delete node;
node = nullptr;
}
// 1.遍历字符串
//2. 查map ,ARR 新建
//3. 继续往下走
void Trietree::insert(string word)
{
cout << "Trietree insert******************" << endl;
if (word ==""){ return; } //1.插入字符为空 返回
char c;
int path = 0;
TrieNodeArr *node=root; //2.取得根结点
for (int i = 0; i < word.length(); i++) //3.遍历字符串
{
char c = word[i]; //4.得到单个字符
c = c - 'a'; //5.是哪条路
if (node->nexts[path] == nullptr) //6 如果没有 创建新的路
{
node->nexts[path] = new TrieNodeArr();//7.新建路
}
node = node->nexts[path]; //8.node移到下一个节点
node->pass++; //9.pass+1 表示走过一次
}
node->end++; //10.一个字符添加完了,e+1
}
bool Trietree::mysearch(string word)
{
cout << "Trietree search******************" << endl;
int m_num = 0;
if (word == "") { return 0; } //1.字符为空 返回
char c;
int path = 0;
TrieNodeArr* node = root; //2.取得根结点
for (int i = 0; i < word.length(); i++) //3.遍历字符串
{
char c = word[i]; //4.得到单个字符
c = c - 'a'; //5.是哪条路
if (node->nexts[path] == nullptr) //6 如果没有路
{
return 0;
}
node = node->nexts[path]; //7.node移到下一个节点
}
if (node != nullptr) //8.如果有下一个节点,返回本节点的e值
{
return node->end;
}
else
{
return 0; //树上没有这个节点,返回0值,一般出现在树“abc”,而实际查询的是“abcdef”
}
return node->end != 0;
}
//加入的字符串,有多少是以pre为前缀的
int Trietree::prefixNumber(string pre)
{
cout << "Trietree prefixNumber******************" << endl;
int m_num = 0;
if (pre == "") { return 0; } //1.字符为空 返回
char c;
int path = 0;
TrieNodeArr* node = root; //2.取得根结点
for (int i = 0; i < pre.length(); i++) //3.遍历字符串
{
char c = pre[i]; //4.得到单个字符
c = c - 'a'; //5.是哪条路
if (node->nexts[path] == nullptr) //6 如果没有
{
return 0;
}
node = node->nexts[path]; //7.node移到下一个节点
}
return node->pass; //8.返回的是本节点上p的值
}
void Trietree_main()
{
cout<<"Trietree******************"<<endl;
Trietree trie;
string str = "li";
cout << trie.mysearch("abc")<< endl;
trie.insert("abc");
trie.insert("abcw");
trie.insert("abce");
trie.insert("abc");
trie.insert("abcr");
trie.insert("abco");
cout << trie.mysearch("abcw") << endl;
cout << trie.prefixNumber("abc") << endl;
}