字典树是一种存储字符串的树形结构,假设有如下场景,给出一堆字符串,然后让你求出以某个字符串为前缀的字符串的个数
比如给你abcd,abce,然后让你求以abc为前缀的字符串的个数
代码如下:
#include <iostream>
#include <string>
using namespace std;
typedef struct _Node
{
int count;
struct _Node * pNodeArr[26];
_Node()
{
count=0;
memset(pNodeArr,NULL,sizeof(struct _Node *)*26);
}
}Node,*PNode;
PNode pRoot;
void InsertTree(string str)
{
if(pRoot==NULL)
{
pRoot=new Node();
}
int i=0;
PNode pTmp=pRoot;
while(i<str.length())
{
char c=str[i];
int index=c-'a';
if(pTmp->pNodeArr[index]==NULL)
{
pTmp->pNodeArr[index]=new Node();
}
pTmp=pTmp->pNodeArr[index];
pTmp->count++;
i++;
}
}
int FindStrNumber(string str)
{
int i=0;
PNode pTmp=pRoot;
while(i<str.length())
{
int index=str[i]-'a';
if(pTmp->pNodeArr[index]==NULL)
{
//以这个模式串作为前缀的字符串不存在,所以返回-1
return -1;
}
pTmp=pTmp->pNodeArr[index];
i++;
}
return pTmp->count;
}
int main()
{
pRoot=NULL;
string str;
cin>>str;
InsertTree(str);
cin>>str;
InsertTree(str);
cin>>str;
InsertTree(str);
cin>>str;
cout<<FindStrNumber(str)<<endl;
return 0;
}
以上是字典树的一个小例子,在搜索引擎应用中,我们经常遇到智能提示或者模糊搜索的例子,比如你输入苹果,搜索框就会列出苹果相关的所有高频词汇,这个也可以使用字典树来实现。
以下的代码出自其它博客,但是它的节点删除代码并不完备,目前已经修正完毕。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef struct _Node
{
bool bEnd;
struct _Node * pNodeArr[256];
_Node()
{
bEnd=false;
memset(pNodeArr,NULL,sizeof(struct _Node *)*256);
}
}Node,*PNode;
class Trie
{
public:
Trie();
~Trie();
void InsertTree(string str);
void FindStr(string str,vector <string> &vecRet);
void FindEndStr(PNode pTmp,string str,vector <string> & vecRet);
void DeleteNode( PNode node);
private:
PNode pRoot;
};
Trie::Trie()
{
pRoot=new Node();
}
Trie::~Trie()
{
DeleteNode(pRoot);
}
void Trie::InsertTree(string str)
{
int i=0;
PNode pTmp=pRoot;
while(i<str.length())
{
//这句话很重要,一个汉字占两个字节,为何pNodeArr长度为256,因为256是2的8次方,一个字节的长度
unsigned char index=(unsigned char )str[i];
if(pTmp->pNodeArr[index]==NULL)
{
pTmp->pNodeArr[index]=new Node();
}
pTmp=pTmp->pNodeArr[index];
i++;
}
pTmp->bEnd=true;
}
void Trie::FindEndStr(PNode pTmp,string str,vector <string> & vecRet)
{
//找到了末尾
if(pTmp->bEnd)
{
vecRet.push_back(str);
return;
}
int i;
//深搜遍历
for(i=0;i<256;i++)
{
if(pTmp->pNodeArr[i]==NULL)
continue;
unsigned char c=(unsigned char )i;
FindEndStr(pTmp->pNodeArr[i],str+(char)c,vecRet);
}
return;
}
void Trie::FindStr(string str,vector <string> & vecRet)
{
int i=0;
PNode pTmp=pRoot;
while(i<str.length())
{
unsigned char index=(unsigned char )str[i];
if(pTmp->pNodeArr[index]==NULL)
{
//以这个模式串作为前缀的字符串不存在,所以给出提示
cout<<"pattern string is not correct,please check it!"<<endl;
return;
}
pTmp=pTmp->pNodeArr[index];
i++;
}
FindEndStr(pTmp,str,vecRet);
}
void Trie::DeleteNode(PNode node)
{
//递归方式释放所有的节点
if(node->bEnd)
{
delete node;
return;
}
int i;
for(i=0;i<256;i++)
{
if(node->pNodeArr[i]==NULL)
continue;
DeleteNode(node->pNodeArr[i]);
}
delete node;
return;
}
int main()
{
Trie * myTrie=new Trie();
myTrie->InsertTree("宝马1系");
myTrie->InsertTree("宝马2系");
myTrie->InsertTree("宝马3系");
string query;
cout<<"please input query:"<<endl;
cin>>query; //输入要检索的query
vector<string> result;
myTrie->FindStr(query,result);
vector<string>::iterator iter = result.begin(); //输出联想结果
cout<<"matching the query list:"<<endl;
for(;iter != result.end();++iter)
{
cout<<*iter<<endl;
}
return 0;
}