字典树与模糊搜索

    字典树是一种存储字符串的树形结构,假设有如下场景,给出一堆字符串,然后让你求出以某个字符串为前缀的字符串的个数

比如给你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;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值