【字典树】字典树的创建(入门详细介绍)
2016-07-29 15:12
204 查看
Part one【何谓字典树】
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。字典树与字典很相似,当你要查一个单词是不是在字典树中,首先看单词的第一个字母是不是在字典的第一层,如果不在,说明字典树里没有该单词,如果在就在该字母的孩子节点里找是不是有单词的第二个字母,没有说明没有该单词,有的话用同样的方法继续查找.字典树不仅可以用来储存字母,也可以储存数字等其它数据。
比如我们创建一个字典树包含下列单词:
inn, int, at, age, adv, ant
是不是非常的类似于新华字典的拼音查词的顺序啊,比如查“生”就要从sh声母开始找e再找n再找g。
Part two【字典树的数据结构】
专门以小写字母为例,可以用数据结构为:typedef struct Trie_node{ int count; // 统计单词前缀出现的次数 struct Trie_node* next[26]; // 指向各个子树的指针 bool exist; // 标记该结点处是否构成单词 }TrieNode , *Trie;
简单版本:
typedef struct Trie{ int v; bool exist; Trie *next[maxn];//maxn是由你规定好的字符串的字符来源决定的,比如小写字母26就够了。 }Trie;
Part three【字典树的生成】
我们需要用到字典树来对字符串进场分析的时候就要将这个字符串放进我们的字典树(就像字典收录新词一样)但是没真正像收录新词那么难。我们只需要2步。1.定义指向根节点的指针P,和一个交换用的指针Q
2.从字符串开始下标到结束(0-len)我们依次将字符做出节点。方法是:将字母由字典序化为数字,则指针next[该字典序]指向的地方为空时我们开辟一个指针空间给Q,将其计数初始化为1。然后从0-MAXN将他next[]指向的全部初始化为NULL。再将P的next[字典序]指针指向Q,P更新为P的next[字典序]。若指针next[字典序]指向的地方已经有节点了,我们将其节点的计数++;更新P为P的NEXT。
符合简单数据结构的版本:void createTrie(char *str) { int len = strlen(str); Trie *p = &root, *q; for(int i = 0; i < len; i++) { int id = str[i]-'a'; if(p->next[id] == NULL) { q = (Trie *)malloc(sizeof(root)); q->v = 1;//初始v==1 for(int j = 0; j < MAXN; j++) q->next[j] = NULL; p->next[id] = q; p = p->next[id]; } else { p->next[id]->v++; p = p->next[id]; } } // p->v = -1;//若为结尾,则将v改成-1表示 }
符合第一个数据结构的版本(分成两个函数):
TrieNode* createTrieNode(){ //其实就是创建根节点 TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode)); node->count = 0; node->exist = false; memset(node->next , 0 , sizeof(node->next)); // 初始化为空指针 return node; } void Trie_insert(Trie root, char* word){ Trie node = root; char *p = word; int id; while( *p ){ id = *p - 'a'; if(node->next[id] == NULL){ node->next[id] = createTrieNode(); } node = node->next[id]; // 每插入一步,相当于有一个新串经过,指针向下移动 ++p; node->count += 1; // 这行代码用于统计每个单词前缀出现的次数(也包括统计每个单词出现的次数) } node->exist = true; // 单词结束的地方标记此处可以构成一个单词 }
Part four【一些功能】
1.查找以特定字符串作为前缀的数目(符合第二个简单数据结构)int findTrie(char *str){ int len = strlen(str); Trie *p = &root; for(int i = 0; i < len; i++){ int id = str[i]-'a'; p = p->next[id]; if(p == NULL) //若为空集,表示不存以此为前缀的串 return 0; // if(p->v == -1) //字符集中已有串是此串的前缀 // return -1; } return p->v; //return -1; //此串是字符集中某串的前缀 }
2.查找某字符串在不在字典中(符合第一个数据结构)
void search_str(Trie_node root,char *str){ //查找串是否在该trie树中 if(NULL==root || *str=='\0'){ printf("trie is empty or str is null\n"); return; } c ac6a har *p=str; Node *t=root; while(*p!='\0'){ if(t->child[*p-'a']!=NULL){ t=t->child[*p-'a']; p++; } else break; } if(*p=='\0'){ if(t->count==0) cout<<"该字符串不在trie树中,但该串是某个单词的前缀\n"; else cout<<"该字符串在该trie树中\n"; } else cout<<"该字符串不在trie树中\n"; }
相关文章推荐
- asp.net入门详细介绍
- 3G入门理论知识详细介绍
- ASP.NET Web API教程 创建Admin视图详细介绍
- JTable的入门详细介绍
- jQuery Deferred和Promise创建响应式应用程序详细介绍
- linux程序设计入门----进程介绍:linux下进程的创建
- 在SQL Server 2005中创建CLR存储过程的详细介绍
- jQuery Deferred和Promise创建响应式应用程序详细介绍
- SD卡中FAT32文件格式快速入门(图文详细介绍)
- SD卡中FAT32文件格式快速入门(图文详细介绍)
- ABAP创建选择屏幕的详细介绍
- Linux程序设计入门系统进程的详细介绍
- 详细介绍Linux批量用户的创建
- wordpress入门基础:wordpress文件系统结构详细介绍
- javascript面向对象入门基础详细介绍
- 详细介绍ASP.NET中利用水晶报表创建图表
- 详细介绍Linux批量用户的创建
- 入门——SQLite详细介绍
- JQuery入门―JQuery程序的代码风格详细介绍
- JQuery入门―JQuery程序的代码风格详细介绍