数据结构-前缀树

  • 前缀树

    • 前缀树定义

      • 前缀树(Trie树),又称字典树、单词查找树或键树,是一种专门设计用于高效存储和检索字符串集合中词项的树形数据结构。其核心特性在于能够快速实现字符串的前缀匹配,极大减少了无谓的字符比较,从而提高了查询效率。
    • 前缀树的特性

      • 前缀编码
        • 每个节点代表一个字符串前缀,从根节点到任一节点的路径上的字符序列构成该节点对应的前缀。
        • 整棵树编码了所有存储在其中的字符串及其所有前缀。
      • 唯一路径
        • 树中不存在两条路径表示相同的前缀,保证了每个前缀在树中仅有一条对应路径,避免了重复存储。
      • 字符导向
        • 每个节点的子节点按字符集(通常是字母表)中的字符进行组织,边标签表示字符。
        • 从一个节点到其子节点的转移代表了字符串中字符的添加或延续。
      • 高效查询
        • 支持快速的字符串前缀查询:只需从根节点开始,沿着待查询前缀的字符顺序逐层向下遍历,即可判断该前缀是否存在。
        • 如果查询路径在树中完整存在,可以立即得知待查询前缀存在于词典中;否则,路径在某处中断,表明不存在。
      • 自动去重
        • 由于每个前缀对应树中唯一的路径,所以在插入过程中,重复的字符串(及其所有前缀)会被自动识别并忽略,无需额外的去重操作。
    • 构建前缀树

      1. 初始化根节点:创建一个空节点作为前缀树的根节点,通常标记为空字符或特殊值(如null、'_'等),表示没有任何字符。
      2. 遍历输入字符串集合:对于输入的每一个字符串(词项),按照以下步骤将其插入到前缀树中。
      3. 插入单个字符串:从根节点开始,逐个字符处理当前字符
        1. 检查当前节点:查看当前节点是否有与当前字符相匹配的子节点。如果有,则沿着该子节点继续处理下一个字符;如果没有,则创建一个新的子节点,将该子节点与当前字符关联,并将其父节点设置为当前节点。
        2. 递归插入:重复步骤a,处理剩余字符,直至字符串结束。
        3. 标记词结束标记:当处理完字符串的最后一个字符时,将该节点标记为词项结束节点(如设置一个布尔标志isEndOfWord为true,或在节点中记录一个计数器end等)以表示当前路径代表一个完整的词项。
      4. 处理完所有字符串:当所有输入字符串都已按照上述过程插入到前缀树中,构建过程结束,得到的树结构即为包含所有输入字符串及其前缀的前缀树。
    • 代码实现

      public class Trie {static class TrieNode{char ch;//字符boolean isEndOfWord;//是否为完整词项//子节点映射Map<Character, TrieNode> children;public TrieNode(char ch) {this.ch = ch;this.isEndOfWord=false;this.children=new HashMap<>();}}private final TrieNode root;public Trie() {this.root = new TrieNode('\0');//用'\0'代表根节点}//1.插入节点public void insert(String word){//从根节点开始插入TrieNode current=root;//遍历待查询字符串每个字符for (char ch:word.toCharArray()){/*** 这句代码 current.children.computeIfAbsent(ch, TrieNode::new) 的作用是*1.在当前节点 current 的子节点映射 children 中查找键为 ch 的条目。* 2.如果找到了,返回与 ch 关联的子节点。* 3.如果没找到,使用 TrieNode 构造函数(通过 TrieNode::new 方法引用)创建一个新的 TrieNode 实例,* 其中字符属性 ch 设置为传递给 computeIfAbsent 的 ch 参数,并将这个新创建的节点作为新值添加到映射中(键为 ch),* 然后返回这个新创建的节点。*/current=current.children.computeIfAbsent(ch,TrieNode::new);}//标记当前节点为词项的结束节点current.isEndOfWord=true;}//2.查询字符串是否存在于前缀树中public boolean search(String word){//从根节点开始TrieNode current = root;//遍历每个字符for (char ch:word.toCharArray()){//获取与当前节点对应的子节点,若不存在返回nullTrieNode node = current.children.get(ch);if (node==null){return false;}current=node;}return current.isEndOfWord;}//3.删除字符串public boolean delete(TrieNode currentNode,String word,int index){//1.若处理完所有字符串if (index==word.length()){//若不是则说明字符串不在树中,返回falseif (!currentNode.isEndOfWord){return false;}//将当前节点的词项结束标点设置为falsecurrentNode.isEndOfWord=false;//检查当前节点是否还有其他节点return currentNode.children.isEmpty();}//2.若还有字符串没有处理完//获取待删除字符串的当前节点char ch = word.charAt(index);//2.1获取当前节点的子节点,若该节点不存在,返回nullTrieNode node = currentNode.children.get(ch);if (node==null){return false;}//2.2若找到子节点,递归删除boolean shouldDeleteCurrentNode = delete(node, word, index + 1);//2.3如果递归删除子节点后返回true,说明子节点没有了其他节点,该子节点已无用可以删除if (shouldDeleteCurrentNode){currentNode.children.remove(ch);//若当前节点无其他子节点,就删除该节点return currentNode.children.isEmpty();}//2.4若此节点无需删除,返回falsereturn false;}
      }
      
    • 前缀树的时间复杂度分析

      • 时间复杂度
        • 插入:构建前缀树时,插入一个字符串的时间复杂度通常为 O(L), 其中 L 是字符串的长度。这是因为插入过程中需要遍历整个字符串,为每个字符创建或查找相应的节点。
        • 查询:查询一个字符串(或其前缀)是否存在于前缀树中的时间复杂度为 O(L),因为同样需要遍历整个字符串,沿着树结构逐个比较字符。
        • 删除:删除一个字符串的时间复杂度理论上也为 O(L),因为需要找到该字符串在树中的完整路径。
      • 空间复杂度
    • 前缀树的应用

      • 自动补全:在搜索引擎、文本编辑器、编程IDE或手机输入法中,当用户输入一部分字符时,系统能够快速列出所有可能的、以当前输入为前缀的完整词汇供用户选择。
      • 词频统计与排序:前缀树可用于统计大量文本数据中各单词出现的频率,并支持按照字母顺序输出。每个节点的计数可以表示以该节点为终点的词频,同时,由于前缀树的天然排序特性,可以按字典序遍历节点及其子节点来获取有序的单词列表。
      • 拼写检查与纠正:在文字处理软件或在线文本编辑平台中,前缀树可以帮助快速识别用户输入的单词是否存在于词库中,从而提示可能的拼写错误。
      • ip路由表查询:在计算机网络中,路由器使用前缀树(通常称为PATRICIA树或Ternary Search Tree)来存储和查找IP地址前缀,以确定数据包的下一跳转发地址。
      • 数据压缩:在某些数据压缩算法中,如LZ78,前缀树用于存储已出现过的字符串及其编码,新出现的字符串可以以其最长前缀作为索引来查找编码,

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

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

相关文章

微信小程序详解

微信小程序是一种无需下载安装即可使用的应用&#xff0c;它实现了应用“触手可及”的梦想&#xff0c;用户只需扫一扫或搜索一下即可打开应用。微信小程序全面开放申请后&#xff0c;企业、政府、媒体、其他组织或个人开发者均可申请注册。 微信小程序的特点包括&#xff1a;…

基于java的商店积分管理系统的设计与实现

功能需求 从功能上可以划分为个人信息管理、商店管理、平台管理、订单管理和数据分析。后台管理系统主要服务于商户和平台管理员&#xff0c;兑换用户是属于商户平台的自有用户&#xff0c;不会被纳入到后台管理系统中来。商户用户可以对自己的积分进行管理&#xff0c;平台管…

echarts下载图片

toolbox: {show: true,//展示工具栏itemSize:20,//icon的大小iconStyle:{borderColor:"#409eff",borderWidth:"3",color:"#fff"},right:"40px",//偏移位置feature: {saveAsImage: {title: "下载图表", //鼠标滑过之后文案na…

用wps自带工具给图片做标注

在wps中&#xff0c;选中wps中的图片&#xff0c;右键选择【编辑】进入图片编辑器&#xff0c;在选项卡面板右侧选择【标注】工具&#xff0c;再选择【添加文本】工具&#xff0c;即可直接在图片上输入文字&#xff0c;标注完成后选择【覆盖原图】就完成标注任务。

【Canvas与艺术】绘制美国星条旗

注意&#xff1a; 该图位置和大小都是按照网上说明精确绘制的。 【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>使…

uniapp 阿里云点播 其他功能

详细记录 阿里云播放器 基础功能 官方文档 继 根据业务开发了其他功能 大家可以结合 上一篇 基础阿里云播放器使用 使用

C++指针的比较

指针可以用关系运算符进行比较&#xff0c;如 、< 和 > 整体的流程&#xff1a; 初始化指针ptr指向数组var的第一个元素。进入while循环&#xff0c;循环条件是ptr的地址小于或等于数组最后一个元素的地址。在循环内&#xff0c;首先打印ptr指向的地址和该地址处的值。然…

Laravel 多语言项目开发

配置 Laravel 已经内置了对多语言的支持&#xff0c;可以使用 Laravel 的本地化&#xff08;localization&#xff09;功能轻松实现多语言。 首先&#xff0c;你需要创建一个语言文件存储你的翻译内容。在 resources/lang 目录下&#xff0c;创建一个你需要的语言文件夹&…

Mybatis学习周报总结

学习Mybatis的周报 在过去的一周里&#xff0c;我们在飞思学习和掌握Mybatis这一优秀的持久层框架。通过谭老师的两周课程&#xff0c;我也有很大的收获。以下是本周的学习总结和收获&#xff1a; 一&#xff1a;Mybatis概述&#xff1a; MyBatis&#xff0c;全称为My Batis …

【Flutter 面试题】 Dart 当中的 .. 表示什么?

【Flutter 面试题】 Dart 当中的 … 表示什么? 文章目录 写在前面口述回答补充说明写在前面 🙋 关于我 ,小雨青年 👉 CSDN博客专家,GitChat专栏作者,阿里云社区专家博主,51CTO专家博主。2023博客之星TOP153。 👏🏻 正在学 Flutter 的同学,你好! 😊 Flutter…

mysql锁表的原因及mysql行锁

mysql锁表的原因 锁是计算机协调多个进程或线程并发访问某一资源的机制。 在数据库中&#xff0c;除传统的计算资源&#xff08;如CPU、RAM、I/O等&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。 如何保证数据并发访问的一致性、有效性是所有数据库…

FA-128晶振用于医疗设备

血糖仪已成为家庭常用的医疗设备,日本爱普生晶振公司生产的2016封装,32MHz贴片晶振可完美应用于医疗器械血糖仪,此款晶振订货型号为X1E000251005900晶振,型号为FA-128,负载电容分8PF,精度10PPM,其尺寸参数为2.0x1.6x0.5mm,符合ROHS标准且无铅,具有封装尺寸超小,高精度,频率范围…

C++ | Leetcode C++题解之第55题跳跃游戏

题目&#xff1a; 题解&#xff1a; class Solution { public:bool canJump(vector<int>& nums) {int n nums.size();int rightmost 0;for (int i 0; i < n; i) {if (i < rightmost) {rightmost max(rightmost, i nums[i]);if (rightmost > n - 1) {r…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(一)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 1 - 2节&#xff09; P1《课程介绍》 开场白&#xff0c;HarmonyOS 的一个简介&#xff0c;话不多说&#xff0c;直接看图吧&…

第十五届蓝桥杯省赛第二场C/C++B组C题【传送阵】题解(AC)

解题思路 由于 a a a 数组是一个 1 1 1 到 n n n 的一个排列&#xff0c;那么形成的一定是如下形式&#xff1a; 一定会构成几个点的循环&#xff0c;或者是几个单独的点。 从任意点开始&#xff0c;如果能进入一个循环&#xff0c;一定可以将整个循环的宝藏都拿走&#x…

QSqlTableModel的canFetchMore、fetchMore效率太低,需替换

问题描述&#xff1a;SQLITE数据库&#xff0c;使用QSqlTableModel获取行数&#xff0c;调用函数rowCount()&#xff0c;仅能获取256行&#xff0c;故使用下面代码获取实际行数&#xff1a; while(m_model->canFetchMore()){m_model->fetchMore();} 但实际使用发现效率…

[vant] 图片预览关闭按钮显示不正常

如果这里显示不正常, 那就应该是按照文档引入了 显示有问题, 直接不引入, 声明一下就行

每日论文推荐:我们距离GPT-4V有多远,最接近GPT-4V的开源多模态大模型

&#x1f4cc; 元数据概览&#xff1a; 标题&#xff1a;How Far Are We to GPT-4V? Closing the Gap to Commercial Multimodal Models with Open-Source Suites作者&#xff1a;Zhe Chen, Weiyun Wang, Hao Tian, Shenglong Ye, Zhangwei Gao, Erfei Cui, Wenwen Tong, Kon…

富格林:可信操作提升做单盈利

富格林指出&#xff0c;黄金市场有涨有跌&#xff0c;有赚有赔&#xff0c;投资黄金并非有机会天天盈利&#xff0c;能够盈利出金最重要的原因还是投资者有正规精妙的技术。在黄金交易中&#xff0c;投资者一定要掌握可信的交易方法&#xff0c;提前布局好策略&#xff0c;这样…

java输入输出流

文件的输入输出流&#xff1a; import java.io.*;public class Stream {//文件输出流public static void SerializableOblect(String path, Object o) throws IOException {FileOutputStream fos null;ObjectOutputStream oos null;fos new FileOutputStream(path);oos ne…