Trie树(前缀树)的应用

问题:在百度或大型网站,你输入“中国”出现“中国制造”,“中国创造”,好多以”中国“为前缀的字符串

这个问题在搜索引擎中常用到,用到Trie树

本文参考了http://www.cnblogs.com/dolphin0520/archive/2011/10/11/2207886.html,深受启发

一.Trie树的原理

利用串构建一个字典树,这个字典树保存了公共前缀信息

下面以英文单词构建的字典树为例,这颗Trie树种每个节点包括26个孩子节点,因为英文中有26个字母

 

节点的结构体

#define MAX  26

typedef struct TrieNode
{
	bool isStr;
	struct  TrieNode *next[MAX];
}Trie;


 

查找的时候,假设字符串长度为len,用BST代价为len*log2(n),用Trie树时间复杂度为len

typedef struct TrieNode
{
	bool isStr;
	struct  TrieNode *next[MAX];
}Trie;
//在以root的Trie树中插入字符串 s
void insert(Trie *root,const char *s)
{
	if(root==NULL||*s=='\0')
		return ;
	int i;
	Trie *p=root;
	while(*s!='\0')
	{
		if(p->next[*s-'a']==NULL)
		{
			Trie *temp=new Trie;
			for(i=0;i<MAX;i++)
				temp->next[i]=NULL;
			temp->isStr=false;
			p->next[*s-'a']=temp;
			p=p->next[*s-'a'];
		}else
		{
			p=p->next[*s-'a'];
		}
		s++;
	}
	p->isStr=true;
}
//查找每个单词存在否
int search(Trie *root,const char *s)
{
	Trie *p=root;
	while(p!=NULL&&*s!='\0')
	{
		p=p->next[*s-'a'];
		s++;
	}
	return (p&&p->isStr==true);
}

//visit  p代表找到的前缀的最后单词,str为从root->next---->p的字符串 用递归的方法 
void vist(Trie *p,string str)
{
	if(!p||p->next==NULL)
		return;
	if(p->isStr)
	{
		cout<<str<<endl;
	}
	for(int i=0;i<MAX;i++)
	{
		char ch='a'+i;
		vist(p->next[i],str+ch);
	}
}
int search_2(Trie *root,const char *s)//找出含有 *s前缀的所有单词
{
	Trie *p=root;
	string str(s);
	while(p!=NULL&&*s!='\0')
	{
		p=p->next[*s-'a'];
		s++;
	}
	if(p==NULL)
	{
		
		return 0;
	}
	int ret=(p&&p->isStr==true);
	vist(p,str);
	cout<<endl<<endl;
	return ret;

}

//删除root的内存
void del(Trie *root)
{
	int i;
	for(i=0;i<MAX;i++)
	{
		if(root->next[i]!=NULL)
		{
			del(root->next[i]);
		}
	}
	delete root;
}

int _tmain(int argc, _TCHAR* argv[])
{

	int i;
	int n,m;
	char s[100]={'\0'};
	Trie *root=new Trie;
	for(i=0;i<MAX;i++)
	{
		root->next[i]=NULL;
	}
	root->isStr=false;
	

	int cycle=1;
	cout<<"exit please input 'end' "<<endl;
	while(cycle)
	{
		cin>>s;
		if(!strcmp(s,"end"))
		{
			cycle=0;
		}else
		{
			insert(root,s);
		}
	}
	cycle=1;
	cout<<"exit search please input 'end' "<<endl;
	while(cycle)
	{
		cin>>s;
		if(!strcmp(s,"end"))
		{
			cycle=0;
		}else{
			if(search_2(root,s)==1)
				cout<<s<<" found "<<endl;
			else
				cout<<s<<" not found "<<endl;

		}
	}
	del(root);


	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值