Trie,来源于(retrieval,取回,数据检索),是一种多叉树,用来存储字母表上的单词非常有用。


Trie经常用来存储动态集合(dynamic set)或者关联数组(associative array),其中的key通常是字符串。跟二叉搜索树不同的是,树中的结点不存储相关的key,而是靠结点在树中的位置来定义key。

在单词拼写检查或者一些能理解自然语言的程序中可以用来存储单词字典。

树中一个结点的所有子孙具有公共前缀。根结点root代表的是空字符串。不是所有的结点都有值。叶子结点和一部分非叶子结点关联着key,也就是所谓的值。

给定数据:
    an,ant,all,allot,alloy,aloe,are,ate,be
相应的trie:


如果字符串的字符集仅是a-z,那么一个节点最多有27个孩子结点(26个字母+1个终止符)。

实现

1、快速但浪费空间,在靠近树的底部将会有大量的null子树,这将浪费大量空间。

type trie = ^ node;
     node = record
               subtrie :array['a'..'z'] of trie;
               IsEndOfWord :boolean
            end;

2、每个结点用一个长度最长为27的链表来表示,链表中的元素用键值对<char,trie>来表示。在这种情况下,在叶子结点处浪费的空间比较少。

function find(word:string; length:integer; t:trie):boolean;
 
   function f(level:integer; t:trie):boolean;
   begin if level=length+1 then
            f:=t^.IsEndOfWord
         else if t^.subtrie[word[level]]=nil then
            f:=false
         else f:=f(level+1, t^.subtrie[word[level]])
   end{f};
 
begin find := f( 1, t )
end{find}

查找

def find(node, key):
    for char in key:
        if char not in node.children:
            return None
        else:
            node = node.children[char]
    return node.value

插入

algorithm insert(root : node, s : string, value : any):
    node = root
    i    = 0
    n    = length(s)
 
    while i < n:
        if node.child(s[i]) != nil:
            node = node.child(s[i])
            i = i + 1
        else:
            break
 
    (* append new nodes, if necessary *)
    while i < n:
        node.child(s[i]) = new node
        node = node.child(s[i])
        i = i + 1
 
    node.value = value

作为hash table的替换

相对于hash table,具有如下优点

1、在最坏情况下查找也具有O(m)(m是字符串的长度)的时间复杂度。优于hash table在最坏情况下(碰撞)的O(N)。

2、Trie没有碰撞。

3、当更多的key加入到Trie中时,不需要提供或者替换hash函数。

4、Trie可以提供按字母表排序的词条条目。

当然,也同样有缺点

1、如果数据保存在随机访问速度比主存慢的硬盘或者一些辅存中,Tries在查找数据时会比hash tables慢。

2、对于浮点数这种key,将会导致很长一串没什么意义的前缀。

3、一些Tries要求的空间比hash table大。因为在Trie中都是为单个的字符单独分配空间,而hash table为整个条目分配一个数据块。

排序

对一个集合的字典序排序可以通过Trie来实现:

1、将所有keys插入Trie。

2、先序遍历输出所有的keys。

这也是一种基数排序

参考资料

wikipedia

Tries前缀树的更多相关文章

  1. HDU1671——前缀树的一点感触

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1671 题目本身不难,一棵前缀树OK,但是前两次提交都没有成功. 第一次Memory Limit Exceed ...

  2. [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  3. 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树

    另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...

  4. trie树(前缀树)

    问题描述:   Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优 ...

  5. 【暑假】[实用数据结构]前缀树 Trie

    前缀树Trie Trie可理解为一个能够快速插入与查询的集合,无论是插入还是查询所需时间都为O(m) 模板如下: +; ; struct Trie{ int ch[maxnode][sigma_siz ...

  6. [Swift]LeetCode208. 实现 Trie (前缀树) | Implement Trie (Prefix Tree)

    Implement a trie with insert, search, and startsWith methods. Example: Trie trie = new Trie(); trie. ...

  7. 1042.D Petya and Array 前缀 + 树状数组

    11.19.2018 1042.D Petya and ArrayNew Point: 前缀 + 树状数组 :树状数组逐个维护前缀个数 Describe: 给你一个数组,一个标记数,问你有多少区间[l ...

  8. 算法进阶面试题07——求子数组的最大异或和(前缀树)、换钱的方法数(递归改dp最全套路解说)、纸牌博弈、机器人行走问题

    主要讲第五课的内容前缀树应用和第六课内容暴力递归改动态规划的最全步骤 第一题 给定一个数组,求子数组的最大异或和. 一个数组的异或和为,数组中所有的数异或起来的结果. 简单的前缀树应用 暴力方法: 先 ...

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

    课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚 ...

  10. python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)

    python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容:(1)利用python中的dict实现Trie:(2) ...

随机推荐

  1. Java过滤器Filter的原理及配置_学习笔记

    Filter中文意思为过滤器.顾名思义,过滤器可在浏览器以及目标资源之间起到一个过滤的作用.例如:水净化器,可以看成是生活中的一个过滤器,他可以将污水中的杂质过滤,从而使进入的污水变成净水. 对于WE ...

  2. 简单的文件上传服务器(上传到FastDFS服务器)

    现在文件服务器使用越来越多,其中FastDFS文件服务器非常出色,可以支持分布式存储,多文件系统集群和多主机备份 环境中使用的文件服务器为172.16.100.10,其中trackerd服务和stor ...

  3. openssl内存分配,查看内存泄露

    openssl内存分配 用户在使用内存时,容易犯的错误就是内存泄露.当用户调用内存分配和释放函数时,查找内存泄露比较麻烦.openssl提供了内置的内存分配/释放函数.如果用户完全调用openssl的 ...

  4. Java日期时间API系列12-----Jdk8中java.time包中的...

    package com.xkzhangsan.time.test; import java.time.LocalDateTime;import java.util.Date; import com.x ...

  5. 从广义线性模型(GLM)理解逻辑回归

    1 问题来源 记得一开始学逻辑回归时候也不知道当时怎么想得,很自然就接受了逻辑回归的决策函数--sigmod函数: 与此同时,有些书上直接给出了该函数与将 $y$ 视为类后验概率估计 $p(y=1|x ...

  6. 吴裕雄--天生自然 人工智能机器学习实战代码:ELASTICNET回归

    import numpy as np import matplotlib.pyplot as plt from matplotlib import cm from mpl_toolkits.mplot ...

  7. [PHP] 报错和“@” - 工作

    以下几点关于报错和@的关系理解 在PHP中使用@加在某个语句前面,可以抑制错误在脚本的执行过程中输出到IO: 如果在某个语句上使用了@,则可以将语句内的各种嵌套的脚本可能存在的报错都会被抑制住: 如果 ...

  8. JXL包大解析;Java程序生成excel文件和解析excel文件内容

    最近需求变化,需要把excel导入 我以前没有做过,所以我查了一些资料 和参考别人的代码 以下是多种方式: import java.io.File; import java.io.FileInputS ...

  9. 常用JS代码片段

    1.隐藏部分数字,如手机号码,身份证号码 1 2 3 function (str,start,length,mask_char){ return str.replace(str.substr(star ...

  10. Python学习笔记(四)函数式编程

    高阶函数(Higher-order function) Input: 1 abs Output: 1 <function abs> Input: 1 abs(-10) Output: 1 ...