浅谈 trie树 及事实上现
Posted wzjhoutai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈 trie树 及事实上现相关的知识,希望对你有一定的参考价值。
定义:又称字典树,单词查找树或者前缀树,是一种用于高速检索的多叉树结构。
如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树。
核心思想:是空间换时间.利用字符串的公共前缀来减少查询时间的开销以达到提高效率的目的。
三个基本性质:
1. 根结点不包括字符,除根结点外每个结点都仅仅包括一个字符。
2. 从根结点到某一结点,路径上经过的字符连接起来,为该结点相应的字符串。
3. 每一个结点的全部子结点包括的字符都不同样。
长处:利用字符串的公共前缀来节约存储空间,最大限度地降低无谓的字符串比較,查询效率比哈希表高。
缺点:假设存在大量字符串且这些字符串基本没有公共前缀,则对应的trie树将很消耗内存。
典型应用:统计和排序大量的字符串(但不仅限于字符串)。所以常常被搜索引擎系统用于文本词频统计
至于Trie树的实现。能够用数组。静态分配空间,也能够用指针动态分配
Trie树的操作
在Trie树中主要有3个操作。插入、查找和删除。
普通情况下Trie树中非常少存在删除单独某个结点的情况,因此仅仅考虑删除整棵树。
如果存在字符串str(都为小写字母),Trie树的根结点为root。i=0,p=root。
typedef struct stu { int n,flag; //n记录前缀及单词的个数,flag标记单词是否存在 struct stu *next[26]; //子节点 }node;
开辟新节点并初始化:
node* creat_node() { node *p=(node *)malloc(sizeof(node)); p->n=p->flag=0; memset(p->next,0,sizeof(p->next)); return p; }
1、插入
1)取str[i],推断p->next[str[i]-‘a‘]是否为空,若为空,则建立结点temp,并将p->next[str[i]-‘a‘]指向temp。然后p指向temp。
若不为空,则p=p->next[str[i]-‘a‘];
2)i++,继续取str[i]。循环1)中的操作,直到遇到结束符‘\0‘。此时将当前结点p中的 flag 置为true。
插入并统计一个字符串
void trie_insert(node *p,char *s) { int i; while(*s!=‘\0‘){ i=*s-‘a‘; if(p->next[i]==0) p->next[i]=creat_node(); p=p->next[i]; s++; p->n++; } p->flag=1; }
2、查找
1)取str[i],推断推断p->next[str[i]-‘a‘]是否为空。若为空。则返回false。若不为空,则p=p->next[str[i]-‘a‘],继续取字符。
2)反复1)中的操作直到遇到结束符‘\0‘,若当前结点p不为空而且 flag 为true,则返回true。否则返回false。
查找一个字符串是否存在,并返回其个数:int trie_search(node *p,char *s) { int i; while(*s!=‘\0‘){ i=*s-‘a‘; p=p->next[i]; if(p==0) return 0; s++; } return p->n; }
3、删除
删除能够以递归的形式进行删除。
递归删除整棵树:
void trie_del(node *root) { int i; for(i=0;i<M;i++) //M为子节点的个数 if(root->next[i]!=NULL) trie_del(root->next[i]); free(root); }
以上是关于浅谈 trie树 及事实上现的主要内容,如果未能解决你的问题,请参考以下文章