二叉树算法之字典树(Trie)详细解读

字典树(Trie,也称前缀树或单词查找树)是一种用于快速查找字符串的数据结构,主要应用于字符串集合的高效存储和查找。字典树特别适合处理具有相同前缀的大量字符串集合,比如单词自动补全、拼写检查等场景。

1. 字典树的定义

字典树是一棵多叉树,通常用于存储字符串。树的每个节点代表一个字符,从根节点到某个节点的路径组成一个字符串。字典树的核心思想是利用字符串的公共前缀来减少存储空间和查找时间。

字典树具有以下几个特性:

  1. 根节点不包含字符,除根节点外每个节点只包含一个字符。
  2. 从根节点到某个节点的路径表示一个字符串的前缀
  3. 每个节点的所有子节点包含的字符都不同
  4. 每个叶子节点代表一个字符串的结束

2. 字典树的结构

字典树由节点构成,每个节点存储以下信息:

  • 字符:该节点表示的字符。
  • 子节点的引用:指向其子节点的引用(即后续字符)。
  • 结束标志:表示从根到该节点的路径是否构成了一个完整的字符串。

每个节点的子节点可以是26个字母(如果是只处理英文小写字母的话),但在实际实现中可以根据需求调整字符集的大小。

3. 字典树的基本操作

字典树支持以下基本操作:

  • 插入(Insert):将一个字符串插入到字典树中。
  • 查找(Search):判断字典树中是否存在某个字符串。
  • 前缀查找(StartsWith):判断字典树中是否存在某个前缀。
3.1 插入操作

插入操作的目的是将一个字符串插入到字典树中。如果该字符串的前缀已经存在于树中,则可以共用已有的节点,否则需要创建新的节点。

步骤

  1. 从根节点开始,逐个检查字符串中的字符。
  2. 对于当前字符,如果在当前节点的子节点中找不到对应的字符节点,则创建一个新的节点。
  3. 移动到该字符的节点,继续处理下一个字符。
  4. 重复该过程,直到字符串的所有字符都处理完毕。
  5. 标记最后一个字符的节点为字符串的结束节点。

时间复杂度:插入操作的时间复杂度为 O(L),其中 L 是要插入的字符串的长度。

3.2 查找操作

查找操作的目的是判断某个字符串是否存在于字典树中。该过程类似于插入操作。

步骤

  1. 从根节点开始,逐个检查字符串中的字符。
  2. 对于每个字符,检查当前节点的子节点中是否存在对应的字符节点。如果不存在,则该字符串不在树中。
  3. 如果所有字符都找到,并且最后一个字符节点标记为字符串结束,则说明该字符串存在。

时间复杂度:查找操作的时间复杂度为 O(L),其中 L 是要查找的字符串的长度。

3.3 前缀查找操作

前缀查找操作的目的是判断是否存在以某个字符串作为前缀的单词。

步骤

  1. 从根节点开始,逐个检查前缀字符串中的字符。
  2. 对于每个字符,检查当前节点的子节点中是否存在对应的字符节点。如果不存在,则该前缀不在树中。
  3. 如果前缀中的所有字符都找到,说明字典树中存在以该前缀开头的单词。

时间复杂度:前缀查找操作的时间复杂度为 O(L),其中 L 是前缀的长度。

4. 字典树的实现

下面是一个字典树的Java实现,支持插入、查找和前缀查找操作:

class TrieNode {// 每个节点包含的字符TrieNode[] children = new TrieNode[26];  // 假设只处理小写字母boolean isEndOfWord;  // 该节点是否为某个单词的结束public TrieNode() {isEndOfWord = false;for (int i = 0; i < 26; i++) {children[i] = null;}}
}class Trie {private TrieNode root;public Trie() {root = new TrieNode();}// 插入一个字符串public void insert(String word) {TrieNode node = root;for (int i = 0; i < word.length(); i++) {int index = word.charAt(i) - 'a';if (node.children[index] == null) {node.children[index] = new TrieNode();}node = node.children[index];}node.isEndOfWord = true;  // 标记字符串结束}// 查找一个字符串public boolean search(String word) {TrieNode node = root;for (int i = 0; i < word.length(); i++) {int index = word.charAt(i) - 'a';if (node.children[index] == null) {return false;  // 字符不存在}node = node.children[index];}return node != null && node.isEndOfWord;  // 判断是否为字符串结束}// 判断是否存在以某个前缀开头的字符串public boolean startsWith(String prefix) {TrieNode node = root;for (int i = 0; i < prefix.length(); i++) {int index = prefix.charAt(i) - 'a';if (node.children[index] == null) {return false;  // 前缀不存在}node = node.children[index];}return true;  // 前缀存在}
}public class Main {public static void main(String[] args) {Trie trie = new Trie();trie.insert("apple");System.out.println(trie.search("apple"));   // 输出 trueSystem.out.println(trie.search("app"));     // 输出 falseSystem.out.println(trie.startsWith("app")); // 输出 truetrie.insert("app");System.out.println(trie.search("app"));     // 输出 true}
}

5. 字典树的应用

字典树因其高效的前缀查找和字符串处理能力,广泛应用于以下场景:

  1. 自动补全:当用户输入部分单词时,可以使用字典树快速找到以该前缀开头的所有单词,从而实现单词补全功能。
  2. 拼写检查:字典树可以用来构建一个词典,然后快速检查某个单词是否在词典中。
  3. 多模式匹配:字典树能够有效地进行多个模式的匹配,比如在文本中查找多个单词的出现位置。
  4. IP 路由查找:字典树的变种(例如 Patricia Trie)常用于网络中的IP路由查找。

6. 字典树的优缺点

优点:
  • 高效的前缀匹配:由于节点间的共享特性,字典树能够快速进行前缀查找操作。
  • 可扩展性强:可以通过简单的调整字符集大小,来适应不同的字符集(如字母、数字等)。
缺点:
  • 空间复杂度高:由于每个节点都需要存储一个完整的子节点数组(如处理26个字母需要26个子节点),在处理大量字符串时可能会占用较多的内存。
  • 不适合短字符串存储:在存储短字符串的情况下,字典树的空间利用率较低。

7. 总结

字典树是一种非常适合处理字符串的高效数据结构,特别在前缀匹配和查找方面具有独特的优势。它通过节点的共享,极大减少了冗余的存储空间,同时能在 O(L)时间内完成插入、查找和前缀查找操作。虽然其空间复杂度相对较高,但通过优化,如压缩字典树或使用更紧凑的存储方式,可以提升性

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

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

相关文章

upload-labs靶场Pass-01

upload-labs靶场Pass-01 分析 查看提示&#xff0c;提示如下 查看源码 function checkFile() {var file document.getElementsByName(upload_file)[0].value;if (file null || file "") {alert("请选择要上传的文件!");return false;}//定义允许上传…

Java-类与对象-下篇

关于类与对象&#xff0c;内容较多&#xff0c;我们分为两篇进行讲解&#xff1a; &#x1f4da; Java-类与对象-上篇&#xff1a;————<传送门:Java-类与对象-上篇-CSDN博客> &#x1f4d5; 面向对象的概念 &#x1f4d5; 类的定义格式 &#x1f4d5; 类的使用 …

ubuntu 安装nginx

sudo apt-get update sudo apt-get install nginx sudo nginx -vsudo systemctl status nginx sudo systemctl start nginx sudo systemctl stop nginx sudo systemctl restart nginx#浏览器输入&#xff1a;http://192.168.31.181/#查看文件结构 cd /etc/nginx sudo cp nginx.…

华为OD机试2024年真题(基站维修工程师)

基站维修工程师&#xff08;200分&#xff09; 小王是一名基站维护工程师&#xff0c;负责某区域的基站维护。 某地方有n个基站(1<n<10)&#xff0c;已知各基站之间的距离s(0<s<500)&#xff0c;并且基站x到基站y的距离&#xff0c;与基站y到基站x的距离并不一定会…

Java 类和对象详解(下)

个人主页&#xff1a;鲤鱼王打挺-CSDN博客 目录 &#x1f497;前言&#xff1a; &#x1f4af;一.static关键字 1. 为什么要使用static 2. static 修饰成员变量&#xff1a; 3. static 修饰成员方法&#xff1a; ​编辑 4. 静态代码块 5.静态导入包 &#x1f4af;二.…

采用分布式锁机制解决Gateway配合Redis实现统一鉴权及分布式会话共享数据不一致问题

在现代分布式系统中&#xff0c;为了实现高可用性和性能优化&#xff0c;通常会采用Gateway与Redis相结合的架构来统一鉴权&#xff0c;并实现分布式会话共享功能。然而&#xff0c;在这种架构中&#xff0c;数据不一致问题是常见的挑战之一。本文将详细探讨如何通过分布式锁机…

Wi-Fi安全性入门(基于ESP-IDF-v4.4)

主要参考资料&#xff1a; Wi-Fi 安全性: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.4/esp32/api-guides/wifi-security.html 目录 1.ESP32 Wi-Fi 安全功能1.1 受保护的管理帧 (PMF)1.2 第三代 Wi-Fi 访问保护 (WPA3-Personal) 1.ESP32 Wi-Fi 安全功能 支…

java 第12天 单例 接口

一.设计模式之单例模式 *饿汉式/醉汉式 步骤&#xff1a; 创建私有化构造方法私有的 静态的 属于本类类型的对象公共的 静态的返回本类对象的方法 // 醉汉式/饿汉式 class Moon{// 1 私有化构造方法private Moon(){}// 2 创建一个私有的静态的属于本类类型的对象private stati…

YOLOv11改进策略【卷积层】| 替换骨干网络 CVPR-2023 FasterNet 高效快速的部分卷积块

一、本文介绍 本文记录的是基于FasterNet的YOLOv11轻量化改进方法研究。FasterNet的网络结构借鉴 CNN 的设计理念,通过提出的PConv减少推理时的计算和内存成本,同时减少通道数并增加部分比例,降低延迟,并通过后续的PWConv来弥补特征信息可能缺失的问题,提高了准确性。本文…

如何在 MySQL 中处理大量的 DELETE 操作??

全文目录&#xff1a; 开篇语前言摘要简介概述DELETE 操作的基本概念常用的 DELETE 方法 核心源码解读简单 DELETE 语句批量 DELETE 示例 案例分析案例1&#xff1a;使用简单 DELETE 删除用户数据案例2&#xff1a;使用分批 DELETE 应用场景演示场景1&#xff1a;用户管理系统场…

linux系统之jar启动脚本

编辑linux启动脚本 执行 vi run_blog 按i 进入编辑&#xff0c;复制以下代码&#xff0c;并根据当前环境修改三个参数。以下是详细完整脚本代码&#xff1a; #!/bin/bash# 配置部分 JAR_PATH"/path/to/your/app.jar" # 替换为你的 JAR 文件的实际路径 L…

Gin框架操作指南07:路由与中间件

官方文档地址&#xff08;中文&#xff09;&#xff1a;https://gin-gonic.com/zh-cn/docs/ 注&#xff1a;本教程采用工作区机制&#xff0c;所以一个项目下载了Gin框架&#xff0c;其余项目就无需重复下载&#xff0c;想了解的读者可阅读第一节&#xff1a;Gin操作指南&#…

【JVM】内存模型

文章目录 内存模型的基本概念案例 程序计数器栈Java虚拟机栈局部变量表栈帧中局部变量表的实际状态栈帧中存放的数据有哪些 操作数栈帧数据 本地方法栈 堆堆空间是如何进行管理的? 方法区静态变量存储 直接内存直接内存的作用 内存模型的基本概念 在前面的学习中,我们知道了字…

Java 8 Stream API:从基础到高级,掌握流处理的艺术

一、Stream&#xff08;流&#xff09;基本介绍 Java 8 API 添加了一个新的抽象称为Stream&#xff08;流&#xff09;&#xff0c;可以让你以一种声明的方式处理数据&#xff0c;这种风格将要处理的元素集合看做一种流&#xff0c;元素流在管道中传输&#xff0c;并在管道中间…

云黑系统全解无后门 +搭建教程

这套系统呢是玖逸之前南逸写的一套云黑系统&#xff0c;功能带有卡密生成和添加黑名单等&#xff0c;源码放在我的网盘里已经两年之久&#xff0c;由于玖逸现在已经跑路了所以现在发出来分享给大家&#xff0c;需要的可以自己拿去而开&#xff0c;反正功能也不是很多具体的自己…

电脑视频剪辑大比拼,谁更胜一筹?

随着短视频的火爆&#xff0c;越来越多的人开始尝试自己动手制作视频&#xff0c;无论是记录生活点滴还是创作个性短片&#xff0c;一款好用的视频剪辑软件是必不可少的。今天&#xff0c;我们就从短视频运营的角度&#xff0c;来聊聊几款热门的电脑视频剪辑软件&#xff0c;看…

docker配置加速器

阿里云 控制台》容器镜像服务》镜像工具》镜像加速器 复制地址&#xff1a;https://ywtoq7bz.mirror.aliyuncs.com 到&#xff1a;etc/docker下&#xff1a;vi daemon.json 格式&#xff1a; { "registry-mirrors": ["加速器地址"] } 注&#xff1…

JavaScript:闭包、防抖与节流

一&#xff0c;闭包 1&#xff0c;什么是闭包 闭包是指一个函数和其周围的词法环境(lexical environment)的组合。 换句话说&#xff0c;闭包允许一个函数访问并操作函数外部的变量。 闭包的核心特性: 函数内部可以访问外部函数的变量即使外部函数已经返回&#xff0c;内部…

Centos7 安装部署Zookeeper

官网地址&#xff1a;https://zookeeper.apache.org/ 1. Zookeeper 介绍 Apache ZooKeeper是一个开源的分布式协调服务&#xff0c;它用于维护配置信息、命名、提供分布式同步以及提供组服务等。ZooKeeper的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来&#x…

一款新开源跨平台的.NET Word(docx)模版导出引擎,完美支持Linux和Mac操作系统(附源码)

前言 在数字化办公日益盛行的今天&#xff0c;文档处理成为了我们日常工作不可或缺的一部分。然而&#xff0c;许多传统的文档处理工具都依赖于特定的操作系统和复杂的组件安装&#xff0c;这无疑给跨平台办公带来了诸多不便。为了解决这一问题&#xff0c;我们找到了一个新的…