字典树(trie)

trie中的键通常是字符串,但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie中的键是一串位元,可以用于表示整数或者内存地址。
1.应用
  • trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。
  • 词频统计:可能有人要说了,词频统计简单啊,一个hash或者一个堆就可以打完收工,但问题来了,如果内存有限呢?所以这里我们就可以用trie树来压缩下空间,因为公共前缀都是用一个节点保存的
  • 前缀匹配:
2.实现方式
trie树实际上是一个DFA,通常用转移矩阵表示。行表示状态,列表示输入字符,(行,列)位置表示转移状态。这种方式的查询效率很高,但由于稀疏的现象严重,空间利用效率很低。也可以采用压缩的存储方式即链表来表示状态转移,但由于要线性查询,会造成效率低下。

三数组Trie

三数组Trie(Tripple-Array Trie)结构包括三个数组:base,next和check.

二数组Trie

二数组Trie(Double-Array Trie)包含base和check两个数组。base数组的每个元素表示一个Trie节点,即一个状态;check数组表示某个状态的前驱状态。


Trie(数字树、字典树、前缀树)

术语trie取自retrieval,也被称为数字树、字典树或前缀树,是一种有序树数据结构,哈希树的变种

与二叉查找树不同,树中节点不存储与节点关联的键,而是通过树中的位置定义键一个节点的所有子孙节点拥有与该节点相同的字符串前缀,根节点与空字符串相关联。并不是每个节点都与值关联,仅叶节点和部分内部节点与值关联

Trie(数字树、字典树、前缀树)

含有键为"A"、"to"、"tea"、"ted"、"ten"、"i"、"in"和"inn"的trie示例。

trie 中的键通常是字符串,但也可以是其它的结构。trie 的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie 中的键是一串位元,可以用于表示整数或者内存地址。


3.基本性质

  • 每个结点都含有R条链接,其中R为字母表的大小。(单词查找树一般都含有大量的空链接,因此在绘制一颗单词查找树时一般会忽略空链接
  • 树中的每个结点中不是包含一个或几个关键字,而是只含有组成关键字的符号。例如,若关键字是数值,则结点中只包含一个数位;若关键字是单词,则结点中只包含一个字母字符我们将每个键所关联的值保存在该键的最后一个字母所对应的结点中
  • 若以树的多重链表来表示Trie树,则树的每个结点中应含有d个指针域。

    若从Trie树中某个结点到叶子结点的路径上每个结点都只有一个孩子,则可将该路径上所有结点压缩成一个“叶子结点”,且在该叶子结点中存储关键字及指向记录的指针等信息

  • 在Trie树中有两种结点:
     分支结点:含有d个指针域和一个指示该结点中非空指针域的个数的整数域。(分支结点所表示的字符是由其指向子树指针的索引位置决定的)
    ② 叶子结点:含有关键字域和指向记录的指针域

4.数据结构及其操作
(1)表示
typedef structTrieNode
{
    NodeKind kind;
    union{
              struct { KeyType K;     Record* infoptr} if;     //叶子节点
              struct { TrieNode* ptr[27];     int num}bh;     //分支节点
             };
} TrieNode , *TrieTree;

(2)查找
从根结点出发,沿给定值相应的指针逐层向下,直至叶子结点,若叶子结点中的关键字和给定值相等,则查找成功若分支结点中给定值相应的指针为空,或叶结点中的关键字和给定值不相等,则查找不成功查找操作的时间依赖于树的深度。
(3)插入和删除

在Trie树上易于进行插入和删除,只是需要相应地增加和删除一些分支结点。

把沿途分支结点中相应的指针域置空,再把其分支结点中的num-1,然后删除叶子结点。当分支结点中num域的值减为1时,便可删除


posted @ 2015-05-24 17:07  cyjseagull  阅读(214)  评论(0编辑  收藏  举报