文章目录

  • Trie 字典树 前缀树
  • 什么是Trie
    • 基本概念
    • 基本性质
    • 应用场景
    • 优点
  • 手写一个trie
    • Trie字典树的前缀查询
    • 实现Trie(前缀树) LeetCode208
    • 添加与搜索单词 - 数据结构设计LeetCode 211
    • 键值映射LeetCode677

Trie 字典树 前缀树

什么是Trie

基本概念

字典树,又称为单词查找树,Trie树,是一种树形结构,它是一种哈希表的变种。

基本性质

  • 根节点不包含字符,除根节点外的每一个子节点都包含一个字符
  • 从根节点到某一节点。路径上经过的字符连接起来,就是该节点对应的字符串
  • 每个节点的所有子节点包含的字符串都不相同

应用场景

典型应用就是用于统计,排序和保存大量的字符串(不仅限于字符串),经常被搜索引擎系统用于文本词频统计。

优点

利用字符串的公共前缀来减少查询时间,最大限度的减少无谓的字符串比较,查询效率比哈希树高。

例如下面是一个统计字符串的字典树

当然这里26是不考虑大小写和其他字符的。

每个节点有若干个指向下个节点的指针
考虑不同的语言,不同的情景,指针数量也不一样
可以用如下的Node结构

class Node{char c;Map<char, Node> next;
}

手写一个trie

import java.util.TreeMap;public class Trie {private class Node{public boolean isWord;public TreeMap<Character, Node> next;public Node(boolean isWord){this.isWord = isWord;next = new TreeMap<>();}public Node(){this(false);}}private Node root;private int size;public Trie(){root = new Node();size = 0;}// 获得Trie中存储的单词数量public int getSize(){return size;}// 向Trie中添加一个新的单词word (非递归写法)public void add(String word){Node cur = root;for (int i = 0 ; i < word.length() ; i ++){char c = word.charAt(i);if (cur.next.get(c) == null)cur.next.put(c, new Node());cur = cur.next.get(c);}if (!cur.isWord){cur.isWord = true;size ++;}}// 查询单词word是否在Trie中public boolean contains(String word){Node cur = root;for (int i = 0 ; i < word.length() ; i ++){char c = word.charAt(i);if (cur.next.get(c) == null)return false;cur = cur.next.get(c);}return cur.isWord;}}

Trie字典树的前缀查询

// 查询是否在Trie中有单词以prefix为前缀
public boolean isPrefix(String prefix){Node cur = root;for (int i = 0 ; i < prefix.length() ; i ++){char c = prefix.charAt(i);if (cur.next.get(c) == null)return false;cur = cur.next.get(c);}return true;
}

实现Trie(前缀树) LeetCode208

https://leetcode-cn.com/problems/implement-trie-prefix-tree/

答案就是我们上面手写的Trie,改掉对应方法名即可。

添加与搜索单词 - 数据结构设计LeetCode 211

https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/

题目描述:

设计一个支持以下两种操作的数据结构:
void addWord(word)
bool search(word)
search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。

示例:

addWord(“bad”)
addWord(“dad”)
addWord(“mad”)
search(“pad”) -> false
search(“bad”) -> true
search(".ad") -> true
search(“b…”) -> true

说明:

你可以假设所有单词都是由小写字母 a-z 组成的。

解答代码:

class WordDictionary {private class Node {boolean isEnd;Node[] next;Node() {isEnd = false;next = new Node[26];}}Node root;/** Initialize your data structure here. */public WordDictionary() {root = new Node();}/** Adds a word into the data structure. */public void addWord(String word) {Node curr = root;int index = 0;for (int i = 0; i < word.length(); i++) {char c = word.charAt(i);index = c - 'a';if (curr.next[index] == null) {curr.next[index] = new Node();}curr = curr.next[index];}curr.isEnd = true;}/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */public boolean search(String word) {return heleper(word, 0, root);}/**** @param word  要查找的单词* @param len  当前已经确定的长度* @param root    根节点* @return*/private boolean heleper(String word, int len, Node root) {//递归出口if (word.length() == len && root.isEnd) return true;if (word.length() == len) return false;char c = word.charAt(len);int index = c - 'a';//通配符if (c == '.') {for (int i = 0; i < 26; i++) {if (root.next[i] != null) {Node curr = root.next[i];if (heleper(word, len + 1, curr)) {return true;}}}} else {root = root.next[index];if (root == null) return false;return heleper(word, len + 1, root);}return false;}
}/*** Your WordDictionary object will be instantiated and called as such:* WordDictionary obj = new WordDictionary();* obj.addWord(word);* boolean param_2 = obj.search(word);*/

键值映射LeetCode677

https://leetcode-cn.com/problems/map-sum-pairs/

问题描述

实现一个 MapSum 类里的两个方法,insert 和 sum。
对于方法 insert,你将得到一对(字符串,整数)的键值对。字符串表示键,整数表示值。如果键已经存在,那么原来的键值对将被替代成新的键值对。
对于方法 sum,你将得到一个表示前缀的字符串,你需要返回所有以该前缀开头的键的值的总和。

示例 1:

输入: insert(“apple”, 3), 输出: Null
输入: sum(“ap”), 输出: 3
输入: insert(“app”, 2), 输出: Null
输入: sum(“ap”), 输出: 5

解答:
首先可以使用基础的HashMap解决

import java.util.HashMap;class MapSum {HashMap<String, Integer> map;/** Initialize your data structure here. */public MapSum() {map = new HashMap<>();}public void insert(String key, int val) {map.put(key, val);}public int sum(String prefix) {int sum = 0;for (String key : map.keySet()){if (key.length() >= prefix.length() && key.substring(0,prefix.length()).equals(prefix))sum += map.get(key);}return sum;}
}/*** Your MapSum object will be instantiated and called as such:* MapSum obj = new MapSum();* obj.insert(key,val);* int param_2 = obj.sum(prefix);*/

使用字典树的方式:

import java.util.TreeMap;class MapSum {private class Node{public int value;public TreeMap<Character, Node> next;public Node(int value){this.value = value;next = new TreeMap<>();}public Node(){this(0);}}private Node root;/** Initialize your data structure here. */public MapSum() {root = new Node();}public void insert(String word, int val) {Node cur = root;for (int i = 0 ; i < word.length() ; i ++){char c = word.charAt(i);if (cur.next.get(c) == null)cur.next.put(c, new Node());cur = cur.next.get(c);}cur.value = val;}public int sum(String prefix) {Node cur = root;for (int i = 0 ; i < prefix.length() ; i ++){char c =prefix.charAt(i);if (cur.next.get(c) == null)return 0;cur = cur.next.get(c);}// 找到所有以cur为根节点的子树将他们的value遍历求和 此时cur指向的已经是prefix最后一个字符即前缀找到了return sum(cur);}private int sum(Node node){// 递归到底的情况 其实不写也没事 不会进入到for中if (node.next.size() == 0)return node.value;int res = node.value;for (char c : node.next.keySet())res += sum(node.next.get(c));return res;}
}/*** Your MapSum object will be instantiated and called as such:* MapSum obj = new MapSum();* obj.insert(key,val);* int param_2 = obj.sum(prefix);*/

可以看到用时比HashMap小很多。

Trie的缺点:空间问题!
仅以小写字母表为例,一个节点就要包含自身的值和一个大小为26的数组,空间大小要用到27n。

数据结构之字典树Trie相关推荐

  1. php trie,数据结构-PHP 字典树(Trie)的实现

    ​这篇文章介绍一下字典树的实现原理,又称单词查找树.Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统 ...

  2. 最优雅的数据结构之一——字典树Trie(Java)

    什么是Trie? 又称单词查找树: 又叫前缀树(prefix tree): Trie树,是一种树形结构,是一种哈希树的变种. 作用: 用以较快速地进行单词或前缀查询: 用于快速检索.统计,排序和保存大 ...

  3. 《恋上数据结构第1季》字典树 Trie

    字典树Trie Trie 简介 Trie 实现 接口设计 源码 测试 数据结构与算法笔记目录:<恋上数据结构> 笔记目录 想加深 Java 基础推荐看这个: Java 强化笔记目录 Tri ...

  4. php 字典树,关于php:数据结构PHP-字典树Trie的实现

    ​这篇文章介绍一下字典树的实现原理,又称单词查找树.Trie树,是一种树形构造,是一种哈希树的变种.典型利用是用于统计,排序和保留大量的字符串(但不仅限于字符串),所以常常被搜索引擎零碎用于文本词频统 ...

  5. 用Python实现字典树(Trie)与双数组字典树(DATrie)

    1. 字典树(Trie) 假如我们把字典中的词以记录的形式(无序)存入数据库中.现给定一串字符,要查找该字符串是否为字典中的词.因为数据库中的记录是无序的,所以,最朴素的方法就逐记录匹配.此方法简单, ...

  6. 基础数据结构(二):字典树、并查集、堆、哈希表、字符串的哈希方式、STL的常见容器及其接口

    文章目录 一.字典树Trie 1 原理 2 Trie字符串统计 3 [LeetCode 208. 实现 Trie (前缀树)](https://leetcode-cn.com/problems/imp ...

  7. 快乐学算法之:字典树Trie

    文章目录 简介 Trie的特性 Trie树和Hashing,BST的对比 Trie树的程序化表示 Trie树的插入 Trie树的搜索 Trie树的删除 Trie树的疑惑 简介 字典树的英文名叫做Tri ...

  8. HDU 1247 Hat’s Words 字典树(Trie树)

    HDU 1247 Hat's Words 字典树(Trie树) 字典树的建立是应该都是一样的 下面是我的做法: 建立完后, 对每一个单词都进行find_string()判断是否符合, 分别对其分成两半 ...

  9. Java实现字典树 Trie

    Java实现字典树 Trie 一.字典树介绍 二.Trie实现以及基本的插入查询操作 数组实现: HashMap实现: Trie插入(这里都以数组实现为例): Trie查询: 三.相关例题: 1.le ...

最新文章

  1. 应用hibernate中的hql语句对日期的操作总结
  2. 你所忽略的DNS---DNS实战及深度解读
  3. linux系统自签发免费ssl证书,为nginx生成自签名ssl证书
  4. cmake指定gcc版本
  5. 关于DataFormWebPart中CreatedModifiedInfo信息的分开使用
  6. 第一个将Palette Mode引入VVC(H.266),阿里云在JVET会议上引起关注
  7. python输出不重复的单词_Python情感分析(比较单词时,不计算文本中重复的单词)...
  8. linux安装gcc运行时库,Linux安装gcc-6.1.0
  9. webstorm 注册码,亲测可用
  10. 2020必火的图神经网络(GNN)是什么?有什么用?
  11. 人工智能 - paddlepaddle飞桨 - 深度学习基础教程 - 个性化推荐
  12. Python实现视频语音和字幕自动审查功能
  13. AttributeError: ‘SMOTE’ object has no attribute ‘fit_sample’
  14. 大学计算机应用基础模拟试题,《大学计算机应用基础》模拟试题.doc
  15. fedora9光盘挂载
  16. VUE+element-ui开发出的美观好看的登录注册模板组件 集成方便
  17. win10 移动硬盘“拒绝访问”解决方案
  18. 运动蓝牙耳机怎么选、几款适合运动的运动耳机
  19. 基于多重继承与信息内容的知网词语相似度计算 - 论文及代码讲解
  20. 教育期刊《中学语文教学参考》杂志简介及投稿须知

热门文章

  1. Linux上wget: 无法解析主机地址
  2. Linux CentOS 8常见命令
  3. 全志T3开发板(4核ARM Cortex-A7)测评合集——从开发板到PLC
  4. 是时候曝光这些低调却挣大钱的互联网公司了!
  5. [2021-11-02] VMware 共享文件夹不显示的问题
  6. 我的编程奋斗历程[四部曲之三]-成为金子篇
  7. SPARQL查询语句
  8. 军工企业信息化建设周涛_乘“云”之势,浪潮ERP布局军工企业云
  9. 角速度与旋转矩阵的转换关系及思考
  10. 【数理方程】傅氏变换拉氏变换