当前位置: 首页 > news >正文

3.8.Trie树

Trie树

Trie 树,又称字典树或前缀树,是一种用于高效存储和检索字符串数据的数据结构,以下是关于它的详细介绍:

定义与原理

  • 定义Trie 树是一种树形结构,每个节点可以包含多个子节点,用于存储字符串集合。它的每个节点代表一个字符串的前缀,从根节点到任意节点的路径上的字符连接起来,就形成了一个字符串。
  • 原理Trie 树利用字符串的公共前缀来减少存储空间和提高检索效率。在插入和查找字符串时,从根节点开始,沿着与字符串中字符对应的子节点向下遍历,直到到达字符串的末尾或者无法继续匹配为止。

基本操作

  • 插入操作:从根节点开始,对于要插入的字符串中的每个字符,检查当前节点的子节点中是否存在该字符对应的节点。如果存在,则移动到该子节点;如果不存在,则创建一个新的子节点,并将其与当前节点连接起来,然后继续处理下一个字符,直到字符串的所有字符都被处理完毕。
  • 查找操作:同样从根节点开始,按照要查找的字符串中的字符顺序,依次检查当前节点的子节点中是否存在匹配的字符。如果在遍历过程中找不到匹配的字符,或者到达了字符串的末尾但当前节点不是一个完整字符串的结尾标志,则表示查找失败;如果能够完整地遍历完字符串,并且最后到达的节点标记为一个完整字符串的结尾,则表示查找成功。
  • 删除操作:先执行查找操作,找到要删除的字符串对应的节点。如果该节点没有子节点,直接删除该节点,并将其父节点中指向该节点的指针置为 null。如果该节点有子节点,需要根据具体情况进行处理,通常是将该节点标记为不再是一个完整字符串的结尾,以实现逻辑上的删除。

应用场景

  • 字符串检索:在搜索引擎、字典查询等应用中,用于快速判断一个字符串是否存在于给定的字符串集合中,或者查找具有特定前缀的所有字符串。
  • 词法分析:在编译器、文本处理等领域,用于对输入的文本进行词法分析,将文本分割成一个个单词或符号。
  • 自动补全:在输入法、代码编辑器等工具中,根据用户输入的前缀,自动提示可能的完整单词或语句。
  • 路由表存储:在计算机网络中,用于存储和查找路由表信息,根据目的 IP 地址的前缀快速确定路由路径。

优缺点

  • 优点:插入和查找操作的时间复杂度通常为O(m),其中 m 是字符串的长度,在处理大量字符串时效率较高;可以高效地支持前缀查询;节点可以共享公共前缀,节省存储空间。
  • 缺点:对于没有公共前缀的字符串集合,Trie 树可能会退化为链表,导致空间浪费和性能下降;删除操作相对复杂,可能需要进行一些额外的处理来维护树的结构和完整性;Trie 树的节点通常需要存储多个指针,对于内存空间有限的环境可能不太友好。

下面是C++中实现Trie树的方法:

节点结构定义

在 C++ 中,通常使用结构体或类来定义 Trie 树的节点。每个节点需要包含一个存储字符的成员变量,以及一个用于存储子节点指针的数组或容器,还需要一个标记来表示该节点是否是一个字符串的结尾。以下是一个简单的节点结构体定义示例:

struct TrieNode {TrieNode* children[26];  // 假设只包含小写英文字母,用数组存储子节点指针bool isEndOfWord;TrieNode() {// 初始化子节点指针为nullptr,标记为不是单词结尾for (int i = 0; i < 26; i++) {children[i] = nullptr;}isEndOfWord = false;}
};

Trie 树的基本操作实现

  • 插入操作:从根节点开始,根据要插入字符串的每个字符,在当前节点的子节点中查找是否存在对应的字符节点。如果不存在,则创建一个新的节点。最后,将字符串末尾的节点标记为单词结尾。示例代码如下:
void insert(TrieNode* root, const std::string& word) {TrieNode* node = root;for (char c : word) {int index = c - 'a';if (node->children[index] == nullptr) {node->children[index] = new TrieNode();}node = node->children[index];}node->isEndOfWord = true;
}
  • 查找操作:从根节点开始,按照要查找字符串的字符顺序,在 Trie 树中依次查找对应的子节点。如果在查找过程中遇到不存在的子节点,或者到达字符串末尾时节点不是单词结尾标记,则表示查找失败。示例代码如下:
bool search(TrieNode* root, const std::string& word) {TrieNode* node = root;for (char c : word) {int index = c - 'a';if (node->children[index] == nullptr) {return false;}node = node->children[index];}return node->isEndOfWord;
}
  • 前缀匹配操作:用于查找是否存在以给定前缀开头的字符串。与查找操作类似,从根节点开始,按照前缀的字符顺序在 Trie 树中查找子节点。只要能够完整地匹配前缀的所有字符,就表示存在以该前缀开头的字符串。示例代码如下:
bool startsWith(TrieNode* root, const std::string& prefix) {TrieNode* node = root;for (char c : prefix) {int index = c - 'a';if (node->children[index] == nullptr) {return false;}node = node->children[index];}return true;
}

完整示例

以下是一个使用上述 Trie 树操作的完整示例:

#include <iostream>
#include <string>// 前面定义的TrieNode结构体和insert、search、startsWith函数int main() {TrieNode* root = new TrieNode();// 插入一些单词insert(root, "apple");insert(root, "app");insert(root, "banana");// 查找单词std::cout << "查找apple: " << (search(root, "apple")? "找到" : "未找到") << std::endl;std::cout << "查找app: " << (search(root, "app")? "找到" : "未找到") << std::endl;std::cout << "查找banana: " << (search(root, "banana")? "找到" : "未找到") << std::endl;std::cout << "查找orange: " << (search(root, "orange")? "找到" : "未找到") << std::endl;// 前缀匹配std::cout << "以app开头的单词: " << (startsWith(root, "app")? "存在" : "不存在") << std::endl;std::cout << "以ban开头的单词: " << (startsWith(root, "ban")? "存在" : "不存在") << std::endl;std::cout << "以ora开头的单词: " << (startsWith(root, "ora")? "存在" : "不存在") << std::endl;return 0;
}

在 C++ 标准库中没有直接提供 Trie 树的数据结构,但可以使用unordered_map等容器来实现类似的功能,STL 中的std::string_view也可以与 Trie 树结合使用,提高字符串处理的效率。

相关文章:

3.8.Trie树

Trie树 Trie 树&#xff0c;又称字典树或前缀树&#xff0c;是一种用于高效存储和检索字符串数据的数据结构&#xff0c;以下是关于它的详细介绍&#xff1a; 定义与原理 定义&#xff1a;Trie 树是一种树形结构&#xff0c;每个节点可以包含多个子节点&#xff0c;用于存储…...

day 21

进程、线程、协程的区别 进程&#xff1a;操作系统分配资源的最小单位&#xff0c;其中可以包含一个或者多个线程&#xff0c;进程之间是独立的&#xff0c;可以通过进程间通信机制&#xff08;管道&#xff0c;消息队列&#xff0c;共享内存&#xff0c;信号量&#xff0c;信…...

基于模板方法模式-消息队列发送

基于模板方法模式-消息队列发送 消息队列广泛应用于现代分布式系统中&#xff0c;作为解耦、异步处理和流量控制的重要工具。在消息队列的使用中&#xff0c;发送消息是常见的操作。不同的消息队列可能有不同的实现方式&#xff0c;例如&#xff0c;RabbitMQ、Kafka、RocketMQ…...

俄语画外音的特点

随着全球媒体消费的增加&#xff0c;语音服务呈指数级增长。作为视听翻译和本地化的一个关键方面&#xff0c;画外音在确保来自不同语言和文化背景的观众能够以一种真实和可访问的方式参与内容方面发挥着重要作用。说到俄语&#xff0c;画外音有其独特的特点、挑战和复杂性&…...

PyTorch使用教程(10)-torchinfo.summary网络结构可视化详细说明

1、基本介绍 torchinfo是一个为PyTorch用户量身定做的开源工具&#xff0c;其核心功能之一是summary函数。这个函数旨在简化模型的开发与调试流程&#xff0c;让模型架构一目了然。通过torchinfo的summary函数&#xff0c;用户可以快速获取模型的详细结构和统计信息&#xff0…...

亚博microros小车-原生ubuntu支持系列:5-姿态检测

MediaPipe 介绍参见&#xff1a;亚博microros小车-原生ubuntu支持系列&#xff1a;4-手部检测-CSDN博客 本篇继续迁移姿态检测。 一 背景知识 以下来自亚博官网 MediaPipe Pose是⼀个⽤于⾼保真⾝体姿势跟踪的ML解决⽅案&#xff0c;利⽤BlazePose研究&#xff0c;从RGB视频…...

C语言之高校学生信息快速查询系统的实现

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之高校学生信息快速查询系统的实现 目录 任务陈述与分析 问题陈述问题分析 数据结构设…...

WPF基础 | WPF 基础概念全解析:布局、控件与事件

WPF基础 | WPF 基础概念全解析&#xff1a;布局、控件与事件 一、前言二、WPF 布局系统2.1 布局的重要性与基本原理2.2 常见布局面板2.3 布局的测量与排列过程 三、WPF 控件3.1 控件概述与分类3.2 常见控件的属性、方法与事件3.3 自定义控件 四、WPF 事件4.1 路由事件概述4.2 事…...

迷宫1.2

先发一下上次的代码 #include<bits/stdc.h> #include<windows.h> #include <conio.h> using namespace std; char a[1005][1005]{ " ", "################", "# # *#", "# # # #&qu…...

RabbitMQ---应用问题

&#xff08;一&#xff09;幂等性介绍 幂等性是本身是数学中的运算性质&#xff0c;他们可以被多次应用&#xff0c;但是不会改变初始应用的结果 1.应用程序的幂等性介绍 包括很多&#xff0c;有数据库幂等性&#xff0c;接口幂等性以及网络通信幂等性等 就比如数据库的sel…...

Unity自学之旅03

Unity自学之旅03 Unity自学之旅03&#x1f4dd; 碰撞体 Collider 基础定义与作用常见类型OnCollisionEnter 事件碰撞触发器 &#x1f917; 总结归纳 Unity自学之旅03 &#x1f4dd; 碰撞体 Collider 基础 定义与作用 定义&#xff1a;碰撞体是游戏中用于检测物体之间碰撞的组…...

pip 相关

一劳永逸法&#xff08;pip怎么样都用不了也更新不了&#xff09;&#xff1a; 重下python(卸载旧版本&#xff09;&#xff1a;请输入访问密码 密码&#xff1a;7598 各版本python都有&#xff0c;下3.10.10 python路径建立&#xff0c;pip无法访问方式&#xff1a; 访问pip要…...

vue request 发送formdata

在Vue中&#xff0c;你可以使用axios库来发送包含FormData的请求。以下是一个简单的例子&#xff1a; 首先&#xff0c;确保你已经安装了axios&#xff1a; npm install axios然后&#xff0c;你可以使用axios发送FormData&#xff0c;例如&#xff1a; import axios from a…...

Android RTMP直播练习实践

前言&#xff1a;本文只是练习&#xff0c;本文只是练习&#xff0c;本文只是练习&#xff01; 直播的核心就是推流和拉流&#xff0c;我们就以RTMP的协议来实现下推流和拉流&#xff0c;其他的协议等我学习后再来补充 1.推流 1.1搭建流媒体服务器&#xff0c;具体搭建方法请参…...

ITIL认证工具商-ManageEngine Servicedesk Plus

ServiceDesk Plus是Zoho Corporation旗下企业IT管理部门ManageEngine提供的统一服务管理解决方案。凭借其无限的可扩展性、情境化的IT和业务集成以及一键式工作流程自动化功能&#xff0c;IT领导者可以使用ServiceDesk Plus有效执行和控制跨不同业务部门和IT功能的复杂工作流程…...

https 的 CA证书和电子签名

https 的攻击者可能使用伪造的一对公私钥与客户端交互, 那么如何确保确实是该服务器的公钥呢? 这就诞生了CA颁发机构 CA颁发机构 服务器和客户端都信任指定的CA颁发机构 服务器上传服务器公钥, CA颁发机构做了什么 服务器公钥哈希, 记为 Hash使用 CA 私钥为 Hash 进行 CA 签…...

频繁刷新网页会对服务器造成哪些影响?

当用户在进行浏览网页的过程中频繁刷新页面时&#xff0c;浏览器会向服务器发送请求&#xff0c;服务器会对该请求进行处理并返回到相应的页面内容中&#xff0c;所以频繁刷新网页会对服务器造成影响&#xff0c;有可能会出现以下问题&#xff1a; 用户每次刷新网页都会向服务器…...

贪心算法(题1)区间选点

输出 2 #include <iostream> #include<algorithm>using namespace std;const int N 100010 ;int n; struct Range {int l,r;bool operator <(const Range &W)const{return r<W.r;} }range[N];int main() {scanf("%d",&n);for(int i0;i&l…...

JavaWeb开发学习笔记--MySQL

MySQL-DQL 基本语法&#xff1a; select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表 having 分组后条件列表 order by 排序字段列表 limit 分页参数 基本查询 关键字&#xff1a;SELECT 查询多个字段&#xff1a;select 字…...

抖音小程序一键获取手机号

前端代码组件 <button v-if"!isFromOrderList"class"get-phone-btn" open-type"getPhoneNumber"getphonenumber"onGetPhoneNumber">一键获取</button>// 获取手机号回调onGetPhoneNumber(e) {var that this tt.login({f…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...