Trie 字典树的两种实现方式

        Trie,又称字典树、单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。从上图可以归纳出Trie树的基本性质:

  • 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
  • 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
  • 每个节点的所有子节点包含的字符互不相同。
  • 从第一字符开始有连续重复的字符只占用一个节点,比如上面的to,和ten,中重复的单词t只占用了一个节点。

字典树的实现有递归与非递归的两种方式:

非递归:

非递归的实现也有两种方式,一种是利用自己创建的节点来实现,具体实现如下:

public class Trie {public static void main(String[] args) {Trie trie = new Trie();trie.add("apple");System.out.println(trie.contains("apple"));System.out.println(trie.isPrefix("app"));}private class TreeNode{public boolean isWord;public TreeMap<Character,TreeNode> next;public TreeNode(){this(false);next = new TreeMap<>();}public TreeNode(boolean isWord){this.isWord = isWord;}}private TreeNode root;private int size;public Trie(){this.root = new TreeNode();this.size = 0;}public int getSize(){return size;}public void add(String str){TreeNode cur = root;for(int i=0;i<str.length();i++){char c = str.charAt(i);if(cur.next.get(c) == null){//新建节点cur.next.put(c, new TreeNode());}//否则,就直接走到该节点位置即可cur = cur.next.get(c);}if(!cur.isWord){//确定cur是新的单词cur.isWord = true;size++;}}public boolean contains(String str){TreeNode cur = root;for(int i=0;i<str.length();i++){char c = str.charAt(i);if(cur.next.get(c) == null) return false;cur = cur.next.get(c);}return cur.isWord;}public boolean isPrefix(String prefix){TreeNode 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对象内部都存在一个TreeNode对象与size对象。其中TreeNode对象内部存在着一个TreeMap,TreeMap内存储着每一个字符与下一个节点的对应关系。

当然,也有另一种实现方式:

class Trie {private Trie[] children;private boolean isWord;public Trie() {children = new Trie[26];isWord = false;}public void insert(String word) {Trie node = this;for(char c : word.toCharArray()){int idx = c - 'a';if(node.children[idx] == null){node.children[idx] = new Trie();}node = node.children[idx];}node.isWord = true;}public boolean search(String word) {Trie node = searchPrefix(word);return node != null && node.isWord;}public boolean startsWith(String prefix) {return searchPrefix(prefix) != null;}public Trie searchPrefix(String word){Trie node = this;for(char c : word.toCharArray()){int idx = c - 'a';if(node.children[idx] != null){node = node.children[idx];}else{return null;}}return node;}
}/*** Your Trie object will be instantiated and called as such:* Trie obj = new Trie();* obj.insert(word);* boolean param_2 = obj.search(word);* boolean param_3 = obj.startsWith(prefix);*/

这个实现方式是每一个Trie对象内部存储自己的Trie[]数组,由此实现节点的对应关系。

递归
public void recursionAdd(String word) {Node cur = root;add(root, word, 0);
}/*** 递归写法调用方法实现递归添加** @param node 传入要进行添加的节点* @param word 传入要进行添加的单词*/
public void add(Node node, String word, int index) {// 确定终止条件,这个终止条件在没加index这个参数时,很难确定// 此时一个单词已经遍历完成了,如果这个结束节点没有标记为单词,就标记为单词if (!node.isWord && index == word.length()) {node.isWord = true;size++;}if (word.length() > index) {char addLetter = word.charAt(index);// 判断trie的下个节点组中是否有查询的字符,如果没有,就添加if (node.next.get(addLetter) == null) {node.next.put(addLetter, new Node());}// 基于已经存在的字符进行下个字符的递归查询add(node.next.get(addLetter), word, index + 1);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/462943.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

更新win11后无法上网

问题描述 系统提示可以更新win11了&#xff0c;然后我就想着更新一下试试。等了好久终于下载完了准备更新&#xff0c;结果提示更新失败&#xff0c;再次更新时下载到一半就停了&#xff0c;然后就发现连不上网了&#xff08;真服了&#xff0c;win11没更新成功&#xff0c;还…

学习Android的第五天

目录 Android ConstraintLayout 约束布局 简介 ConstraintLayout 约束布局分类 1、相对定位 (Relative positioning) 2、边距 ( Margins ) 3、居中定位和偏向 ( Centering positioning and bias ) 4、环形定位 ( Circular positioning ) 5、对可见性的处理 ( Visibilit…

介绍 MSTest Runner – CLI、Visual Studio 等

作者&#xff1a;Amaury Lev Marco Rossignoli Jakub Jareš 排版&#xff1a;Alan Wang 我们很高兴推出 MSTest 运行器&#xff0c;这是一款全新的轻量级 MSTest 测试运行器。这个新的运行器使测试更加便携和可靠&#xff0c;运行速度更快&#xff0c;并且具有可扩展性&#x…

Unity类银河恶魔城学习记录2-1.2.3.4.5 背景和摄像机相关设置 P42-p45

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili ParallaxBackground.cs using System.Collections; using System.Collect…

【从Python基础到深度学习】4. Linux 常用命令

1.配置root用户密码 root用户为系统默认最高权限用户&#xff0c;其他用户密码修改命令与root用户修改密码命令相同 sudo passwd root 2.添加用户&#xff08;henry&#xff09; sudo useradd -m henry -s /bin/bash 3.配置henry用户密码 Xshell下连接新用户&#xff08;hen…

跨平台监控管理工具ServerBee

大年初一&#xff0c;给各位拜年&#xff0c;恭祝大家龙年大吉&#xff0c;新春快乐~&#xff01; 本文是应网友 博茨瓦纳 的要求折腾的&#xff1b; 什么是 ServerBee &#xff1f; ServerBee 是一款支持跨平台集监控、管理和终端的效率工具&#xff0c;支持 Linux 、Windows …

肯尼斯·里科《C和指针》第12章 使用结构和指针(1)链表

只恨当时学的时候没有读到这本书&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c;&#xff0c; 12.1 链表 有些读者可能还不熟悉链表&#xff0c;这里对它作一简单介绍。链表(linked list)就一些包含数据的独立数据结构&#xff08;通常称为节点&#xff09;的集…

【JAVA WEB】盒模型

目录 边框 内边距 基础写法 复合写法 外边距 基础写法 复合写法 块级元素的水平居中 弹性布局 设置行内元素的属性 &#xff0c;span 每一个HTML元素就相当于是一个矩形的“盒子” 这个盒子由以下这几个部分构成&#xff1a; 1.边框 border 2.内容 content 3.内边…

如何在 emacs 上开始使用 Tree-Sitter(windows)

文章目录 如何在emacs上开始使用Tree-Sitter&#xff08;windows&#xff09; 如何在emacs上开始使用Tree-Sitter&#xff08;windows&#xff09; 参考&#xff1a;“How to Get Started with Tree-Sitter”。 首先要有一个可运行的emacs&#xff0c;并且它支持Tree-Sitter&…

谷歌 DeepMind 联合斯坦福推出了主从式遥操作双臂机器人系统增强版ALOHA 2

谷歌 DeepMind 联合斯坦福推出了 ALOHA 的增强版本 ——ALOHA 2。与一代相比&#xff0c;ALOHA 2 具有更强的性能、人体工程学设计和稳健性&#xff0c;且成本还不到 20 万元人民币。并且&#xff0c;为了加速大规模双手操作的研究&#xff0c;ALOHA 2 相关的所有硬件设计全部开…

java的excel列行合并模版

1.效果 2.模版 <tableborder"1"cellpadding"0"cellspacing"0"class"tablebor"id"TABLE"><tr align"center" class"bg217"><td style"background-color: #008000; color: #ffffff;p…

Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置,Kotlin

Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置&#xff0c;Kotlin 借鉴 Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心&#xff0c;Kotlin&#xff08;2&#xff09;-CSDN博客 在此基础上实现手指在屏幕上点击后&…