Trie树

来源:互联网 发布:如何查看淘宝宝贝类目 编辑:程序博客网 时间:2024/06/11 09:46

参考:http://blog.csdn.net/hackbuteer1/article/details/7964147#reply


知识简介  

      字典树(Trie)可以保存一些字符串->值的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都是 key-value 映射,只不过 Trie 的 key 只能是字符串。
  Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度都为 O(k) ,其中 k 为 key 的长度,与 Trie 中保存了多少个元素无关。Hash 表号称是 O(1) 的,但在计算 hash 的时候就肯定会是 O(k) ,而且还有碰撞之类的问题;Trie 的缺点是空间消耗很高。
  至于Trie树的实现,可以用数组,也可以用指针动态分配,我做题时为了方便就用了数组,静态分配空间。
      Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
      Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的

Trie树的操作
    在Trie树中主要有3个操作,插入、查找和删除。一般情况下Trie树中很少存在删除单独某个结点的情况,因此只考虑删除整棵树。
1、插入
  假设存在字符串str,Trie树的根结点为root。i=0,p=root。
  1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;
   若不为空,则p=p->next[str[i]-97];
  2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的 exist置为true。

void Trie_insert(Trie node,char* p){while( *p ){if(node->next[*p-'a'] == NULL){ node->next[*p-'a'] = Trie_createroot();}node = node->next[*p-'a'];p++;node->count += 1;}}



2、查找
  假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root
  1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。
  2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且 exist 为true,则返回true,否则返回false。

int Trie_search(Trie root, char* word){char *p = word;Trie node = root;int id;while( *p ){id = *p-'a';node = node->next[id];if(node == NULL){return 0;}++p;}return node->count;}


3、删除
  删除可以以递归的形式进行删除。



关于前缀查询的应用主要代码

typedef struct  Trie_node { int count;                           //在每次插入时统计前缀的个数struct Trie_node* next[26]; //指向子树的指针数组bool exist;//标记该到节点是否已经组成单词}TrieNode , *Trie;TrieNode* Trie_createroot(){            //初始化字典树的根节点TrieNode* p = new TrieNode();p->count = 0;p->exist = false;memset(p->next,0,sizeof(p->next));return p;}void Trie_insert(Trie node,char* p){while( *p ){if(node->next[*p-'a'] == NULL){ node->next[*p-'a'] = Trie_createroot();}node = node->next[*p-'a'];p++;node->count += 1;        //统计每个单词前缀出现的次数(也包括统计每个单词出现的次数)}}int Trie_search(Trie root, char* word){   //查找char *p = word;Trie node = root;int id;while( *p ){id = *p-'a';node = node->next[id]; if(node == NULL){return 0;}++p;}return node->count;}