trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高。

trie树的建树:

比如有字符串”ab” ,“adb”,“adc”   可以建立字典树如图:

树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等。插入字符串ab时,next[‘a’-‘a’]即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next[‘d’-‘a’]即next[3]为空,这时申请一个结点tmp放在next[3]的位置,接下来,tmp的后向结点tmp->next[‘a’-‘a’]即tmp->next[0]为空,在申请一个结点放在tmp->next[0]的位置。 
插入字符串dc时,检查head->next[3]不为空,然后检查tmp->next[2]为空,这时申请一个结点放在tmp->next[2]的位置。

字典树的建树过程就是字符串不断插入的过程。

字典树的查找可以按照如下步骤进行:比如查找字符串”dc”,先检查head->next[3]是否为空,如果为空返回,若不为空,再检查下个结点的next[2]是否为空,如果为空返回

2. 字典树的应用

(1)用于查字符串的字典树:

用于查找字符串的字典树,输的结点结构体可以定义为:

struct node
{
bool isword;
node *next[26];
};

其中isword用于判断从根节点到此结点是否构成一个单词,next数组用于指示26个结点指针,这里假定所有单词都使用小写英文字母来表示。

# include <iostream>
# include <cstdlib>
# include <cstring>
using namespace std;
struct node
{
bool isword;
node *next[26];
};

node *head=NULL;
void insert(char s[])
{
node *p=head;
int len=strlen(s);
int i=0;
for(i=0;i<len;i++)
{
	if(p->next[s[i]-'a']==NULL)
	{
	node *tmp=(node *)malloc(sizeof(node));
	tmp->isword=false;
	int j=0;
	for(j=0;j<26;j++)
		tmp->next[j]=NULL;
	p->next[s[i]-'a']=tmp;
	p=tmp;
	}
	else
		p=p->next[s[i]-'a'];
}
p->isword=true;
}

int find(char *s)
{
node *p=head;
if(p==NULL)
	return 0;
while(p!=NULL&&*s!='\0')
{
	if(p->next[(*s)-'a']){
		p=p->next[(*s)-'a'];
		s++;
	}
	else
		return 0;
}
return (p!=NULL&&(*s)=='\0'&&p->isword==true);
}
void destroy(node *head)
{
	if(head!=NULL){
int i;
for(i=0;i<26;i++)
{
	if(head->next[i]!=NULL)
	destroy(head->next[i]);

}
	free(head);
}
}
int main(void)
{
	head=(node *)malloc(sizeof(node));
	head->isword=false;
	int i=0;
	for(;i<26;i++)
		head->next[i]=NULL;
	char s1[20]="hello";
	char s2[20]="world";
	char s3[20]="hell";
	insert(s2);
	insert(s1);
	cout<<find(s1)<<endl;
	destroy(head);
	system("pause");
	return 0;
}

(2)用于统计前缀出现次数的字典树

用于统计前缀出现次数的字典树,其树的结点结构体可以定义如下:

struct node
{
int num;
node *next[26];
};

其中num为这个本前缀出现的次数,next数组表示的含义与上面类似。

# include <iostream>
# include <string>
# include <cstdlib>
using namespace std;

struct node
{
int num;
node *next[26];
};

node *head=0;

int main()
{
	char s[20];
	void insert(char a[]);
	int find(char a[]);
	void destroy(node *head);
	int i;
	head=new node;
	for(i=0;i<26;i++)
		head->next[i]=NULL;
	cout<<"input words and terminate by '#'"<<endl;
	while(cin>>s&&s[0]!='#')
	{
	insert(s);
	}
	cout<<"input the prefix"<<endl;
	cin>>s;
	cout<<"the number is"<<endl;
	cout<<find(s)<<endl;
	destroy(head);
	system("pause");
	return 0;
}

void insert(char a[])
{
node *s=head;
int i;
int len=strlen(a);
for(i=0;i<len;i++)
{
int k=a[i]-'a';
if(s->next[k]==NULL)
{
node *tmp=new node;
tmp->num=1;
int j=0;
for(j=0;j<26;j++)
	tmp->next[j]=NULL;
s->next[k]=tmp;
s=s->next[k];
}
else
{
	s=s->next[k];
	s->num++;
}
}

}

int  find(char a[])
{
int i;
int len=strlen(a);
int count=0;
node *s=head;
for(i=0;i<len;i++)
{
	int k=a[i]-'a';
	if(s->next[k]==NULL)
		{count=0;
	return count;
	}
	else
	{
		s=s->next[k];
		count=s->num;
	}
}
return count;
}

void destroy(node *head)
{
	if(head!=NULL){
int i;
for(i=0;i<26;i++)
{
	if(head->next[i]!=NULL)
	destroy(head->next[i]);

}
	free(head);
}
}

(3)用于字符串排序的字典树

用于字符串排序的字典树,树的结点结构体可以定义如下:

struct node
{
	int count;
	char *s;
	node *next[26];
};

其中count用于保存某个字符串出现的次数,s用于保存到本节点为止的字符串,next数组含义与前面的类似。

# include <iostream>
# include <cstdlib>
# include <cstring>
using namespace std;
int cnt=0;
struct node
{
	int count;
	char *s;
	node *next[26];
};
node *head=NULL;
void insert(char str[])
{
node *p=head;
int len=strlen(str);
int i=0;
for(;i<len;i++)
{
	if(p->next[str[i]-'a']==NULL)
	{
	node *tmp=(node *)malloc(sizeof(node));
	tmp->count=0;
	tmp->s=(char *)malloc(50*sizeof(char));
	int j;
	for(j=0;j<26;j++)
		tmp->next[j]=NULL;
	strcpy(tmp->s,p->s);
	//strcat(tmp->s,p->s);
	//strcat(tmp->s,str[i]);
	//strcat(tmp->s,'\0');
	char ctmp[2]={str[i],'\0'};
	strcat(tmp->s,ctmp);
	p->next[str[i]-'a']=tmp;
	p=tmp;
	}
	else
		p=p->next[str[i]-'a'];
}
p->count++;
}

void sort(node *head,char **str)
{
	if(head!=NULL)
	{
		if(head->count>0)
		{
			for(int i=0;i<head->count;i++)
				str[cnt++]=head->s;

		}
		for(int j=0;j<26;j++)
				sort(head->next[j],str);
	}
}
void destroy(node *head)
{
	if(head!=NULL){
int i;
for(i=0;i<26;i++)
{
	if(head->next[i]!=NULL)
	destroy(head->next[i]);

}
	free(head);
}
}
int main(void)
{
	head=(node *)malloc(sizeof(node));
	int i=0;
	for(i=0;i<26;i++)
		head->next[i]=NULL;
	head->count=0;
	head->s=(char *)malloc(50*sizeof(char));
	head->s[0]='\0';
	char s1[20]="hello";
	char s2[20]="world";
	char s3[20]="helloa";
	char *str[3]={s1,s2,s3};
	insert(str[0]);
	insert(str[1]);
	insert(str[2]);
	sort(head,str);
	cout<<str[0]<<endl;
	cout<<str[1]<<endl;
	cout<<str[2]<<endl;
	destroy(head);
system("pause");
return 0;
}

trie树(字典树),布布扣,bubuko.com

时间: 2024-08-05 07:07:29

trie树(字典树)的相关文章

剑指Offer——Trie树(字典树)

剑指Offer--Trie树(字典树) Trie树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高. Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子右兄弟的方法建树的话,可能会好点.可见,优

Hash树(散列树)和Trie树(字典树、前缀树)

1.Hash树 理想的情况是希望不经过任何比较,一次存取便能得到所查的记录, 那就必须在记的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和一个唯一的存储位置相对应.因而在查找时,只要根据这个对应关系f找到 给定值K的像f(K).由此,不需要进行比较便可直接取得所查记录.在此,我们称这个对应关系为哈希(Hash)函数,按这个思想建立的表为哈希表. 在哈希表中对于不同的关键字可能得到同一哈希地址,这种现象称做冲突.在一般情况下,冲突只能尽可能地减少,而不能完全避免.因为哈希函数是从

【数据结构】前缀树/字典树/Trie

[前缀树] 用来保存一个映射(通常情况下 key 为字符串  value 为字符串所代表的信息) 例如:一个单词集合 words = {  apple, cat,  water  }   其中 key 为单词      value 代表该单词是否存在 words[ 'apple' ] = 存在     而     word[ ' abc' ] = 不存在 图示:一个保存了8个键的trie结构,"A", "to", "tea", "ted

【学习总结】数据结构-Trie/前缀树/字典树-及其最常见的操作

Trie/前缀树/字典树 Trie (发音为 "try") 或前缀树是一种树数据结构,用于检索字符串数据集中的键. 一种树形结构,是一种哈希树的变种. 典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高. 应用: 自动补全 END 原文地址:https://www.cnblogs.com/anliux/p/12590368.html

9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c        相关测试数据

Trie树/字典树

Trie树结构 Trie树是一种树形数据结构,又称为单词查找树.字典树,是一种用于快速检索的多叉树结构.典型应用是统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.     它的主要设计思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销.它的优点是可以最大限度的减少无谓的字符串比较,查询效率比哈希表高:缺点是内存消耗非常大. Trie树基本特性 根节点不包含字符,除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点

常用算法之Trie【字典树,前缀树】

Trie中文名又叫做字典树,前缀树等,因为其结构独有的特点,经常被用来统计,排序,和保存大量的字符串,经常见于搜索提示,输入法文字关联等,当输入一个值,可以自动搜索出可能的选择.当没有完全匹配的结果时,可以返回前缀最为相似的可能. 其实腾讯的面试题有一个:如何匹配出拼写单词的正确拼写.其实用匹配树非常合适. 基本性质: 1.根节点不含有字符,其余各节点有且只有一个字符. 2.根节点到某一节点中经过的节点存储的值连接起来就是对应的字符串. 3.每一个节点所有的子节点的值都不应该相同. 借用一下维基

Trie树&mdash;字典树(单词查找树)

Trie树,又称字典树,单词查找树.它来源于retrieval(检索)中取中间四个字符构成的.用于存储大量的字符串以便支持快速模式匹配.主要应用在信息检索领域. Trie有三种结构:标准Trie(standard trie),压缩Trie,后缀Trie(suffix trie). 1.标准Trie 标准Trie树的结构:所有含有公共前缀的字符串将挂在树中同一个结点下.实际上trie简明的存储于串集合汇总的所有公共前缀.加入有这样一个字符串集合X{bear,bell,bid,bull,buy,se

Trie树/字典树题目(2017今日头条笔试题:异或)

1 /* 2 本程序说明: 3 4 [编程题] 异或 5 时间限制:1秒 6 空间限制:32768K 7 给定整数m以及n各数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个. 8 输入描述: 9 第一行包含两个整数n,m. 10 11 第二行给出n个整数A1,A2,...,An. 12 13 数据范围 14 15 对于30%的数据,1 <= n, m <= 1000 16 17 对于100%的数据,1 <= n, m,

[转载]Trie树|字典树(字符串排序)

有时,我们会碰到对字符串的排序,若采用一些经典的排序算法,则时间复杂度一般为O(n*lgn),但若采用Trie树,则时间复杂度仅为O(n). Trie树又名字典树,从字面意思即可理解,这种树的结构像英文字典一样,相邻的单词一般前缀相同,之所以时间复杂度低,是因为其采用了以空间换取时间的策略. 下图为一个针对字符串排序的Trie树(我们假设在这里字符串都是小写字母),每个结点有26个分支,每个分支代表一个字母,结点存放的是从root节点到达此结点的路经上的字符组成的字符串. 将每个字符串插入到tr