Trie树的功能、思想、实现都写在代码注释中了
使用:
Trie trie = new Trie([TypeCase]);
trie.
TypeCase=
Bit //二进制
Number // 0-9数字
LowerCase //小写字母
这样就可以使用Trie树类了
代码:
//—————————————————————–
#pragma once
/** 功能: 1、字符串检索 检索/查询功能是Trie树最原始的功能。 2、搜索引擎系统 用于文本词频统计 3、字符串排序 4、前缀匹配 5、作为其他数据结构和算法的辅助结构(如AC自动机) */
/** Trie树特性: 1)根节点不包含字符,除根节点外每一个节点都只包含一个字符。 2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 3)每个节点的所有子节点包含的字符都不相同。 4)如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。 5)插入查找的复杂度为O(n),n为字符串长度。 */
enum TypeCase
{
Bit = 2,//二进制
Number = 10,//0-9
LowerCase = 26//小写字母
};
class Trie
{
public:
explicit Trie(TypeCase _next) :count(0), typeCase(_next),fail(nullptr) {
next = new Trie*[typeCase];
for (auto beg(0); beg < typeCase; ++beg) next[beg] = nullptr;};
Trie() = delete;
~Trie(){delete []next;};
/** 1、插入: 假设存在字符串str,Trie树的根结点为root。i=0,p=root。 1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;若不为空,则p=p->next[str[i]-97]; 2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的 exist置为true。 */
bool InsertTrie(const std::string &str);
/** 2、查找 假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root 1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。 2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且 exist 为true,则返回true,否则返回false。*/
bool SearchTrie(const std::string &str);
private:
size_t count;// 统计单词前缀出现的次数
TypeCase typeCase;//Trie tree's type
Trie* fail;//AC自动机Fail指针
Trie **next; // 指向各个子树的指针
};
inline bool Trie::InsertTrie(const std::string &str)
{
auto strIterator(str.begin());
auto strEnd(str.end());
auto trieCount(0);
// ReSharper disable once CppInitializedValueIsAlwaysRewritten
size_t strIteratorToInt(0);
auto trieThis(this);
while (strIterator != strEnd)
{
switch(typeCase)
{
case 2: strIteratorToInt = static_cast<size_t>(*strIterator) - 48;
if (strIteratorToInt < 0 || strIteratorToInt>1) return false;
break;
case 10:
strIteratorToInt = static_cast<size_t>(*strIterator) - 48;
if (strIteratorToInt < 0 || strIteratorToInt>9) return false;
break;
case 26:strIteratorToInt = static_cast<size_t>(*strIterator) - 97;
if (strIteratorToInt < 0 || strIteratorToInt>26) return false;
break;
default:return false;
}
if (!trieThis->next[strIteratorToInt]) {
// ReSharper disable once CppNonReclaimedResourceAcquisition
auto temp = new Trie(typeCase);
temp->count = trieThis->count + 1;
trieThis->next[strIteratorToInt] = temp;
trieThis = temp;
}
else trieThis = trieThis->next[strIteratorToInt];
++strIterator;
}
return true;
}
inline bool Trie::SearchTrie(const std::string &str)
{
auto strIterator(str.begin());
auto strEnd(str.end());
// ReSharper disable once CppInitializedValueIsAlwaysRewritten
auto strIteratorToInt(0);
auto trieThis(this);
while (strIterator != strEnd)
{
switch (typeCase)
{
case 2: strIteratorToInt = static_cast<size_t>(*strIterator) - 48;//限制非法输入
if (strIteratorToInt < 0 || strIteratorToInt>1) return false;
break;
case 10:
strIteratorToInt = static_cast<size_t>(*strIterator) - 48;//限制非法输入
if (strIteratorToInt < 0 || strIteratorToInt>9) return false;
break;
case 26:strIteratorToInt = static_cast<size_t>(*strIterator) - 97;//限制非法输入
if (strIteratorToInt < 0 || strIteratorToInt>26) return false;
break;
default:return false;
}
if (trieThis->next[strIteratorToInt]) {
trieThis = trieThis->next[strIteratorToInt];
}
else return false;
++strIterator;
}
return true;
}