前缀树概念

news2024/12/28 20:25:50

前缀树(prefix tree)
准备一个Str[],数组中元素有[“abc”,“bcd”,“abg”,“bcde”,“qwe”],如何将数组中元素加到树中呢?
从最开始的字符串abc说,第一个字符是a,从一个空的头节点出发,看有没有走向a字符的路,没有,就创建一条,字符不放在节点上,字符永远在路上,b也同理,从a节点出发,没有b的就创建,最终创建出来的就是下图这样。
在这里插入图片描述
后面的字符串原理相同,从头节点出发,看有没有走向该字符的路,有就复用没有则创建,所以根据上面的数组构建出来的前缀树是这样的。
在这里插入图片描述
所以可以看出来,前缀树是一课多叉树
因为前缀树中,节点不存放值,所以封装一些额外的信息属性,比如说pass(构建树的过程中,该节点经过几次),end(当前节点,有多少字符串以它结尾)。根据上面数组中的例子,算下来每一节点的情况是这样。

树构建完之后,就可以根据这个树的结构查看是否以xxx开头的字符串,以及树中是否存在xxx字符串。
在这里插入图片描述

所以说,前缀树的结构,比hash表结构强的地方就在于,前缀树可以查找树中是否存在以xxx开始的前缀字符串。

Hash表
之前的帖子中说过,hash表的增删改查都是O(1)的常数时间操作,但前提是不考虑单样本量大小的情况下。
如果说添加的都是32位的整型Int类型数字,那不用考虑,但如果添加的是一个很大的字符串(这个字符串存着一本书的内容)。那此时就不是O(1)的长度。是O(K)的操作(K = 字符串长度)。
所以说,如果往Hash表中添加数据,如果单样本大小无足轻重,则认为是O(1),如果单样本很大,那就不是O(1),因为Hash表会遍历字符串的长度计算出Hash值才知道自己再hash表中如何组织,添加100W个字符串,平均长度是100,那Hash表单次添加就是O(100)的复杂度。
添加对象也是O(1)操作,因为添加的是对象内存地址。

Java代码实现

public static class Node {
        private int pass;
        private int end;
        private Node[] nexts;
        //private HashMap<Integer,Node> nexts;

        public Node() {
            pass = 0;
            end = 0;
            //表达下层有多少路
            //先以26个小写英文字母为例,所以长度为26 a - z
            //用底层节点是否为null,标记这条路是否存在。
            // 0   a
            // 1   n
            // 2   c
            //25   z
            //nexts[i] == null  i方向的路不存在
            //nexts[i] != null  i方向的路存在
            nexts = new Node[26];
            //如果字符种类多,则用上面的hashMap存储,key 就是字符的ascII转成数字的形式。
        }
    }

    public static class Trie {
        private Node root;

        public Trie() {
            root = new Node();
        }

        //遍历,将字符拆开,挂在树上
        public void insert(String str) {
            if (str == null) {
                return;
            }
            char[] tmp = str.toCharArray();
            Node node = root;
            node.pass++;
            int path = 0;
            //遍历字符
            for (int i = 0; i < tmp.length; i++) {
                //通过 - 'a' 来判断下一节点是否存在,如果存在下标是什么
                path = tmp[i] - 'a';
                if (node.nexts[path] == null) {
                    node.nexts[path] = new Node();
                }
                node = node.nexts[path];
                node.pass++;
            }
            node.end++;
        }

        //查询str在树中加入过几次
        public int search(String str) {
            if (str == null) {
                return 0;
            }
            char[] tmp = str.toCharArray();
            Node node = root;
            int path = 0;
            for (int i = 0; i < tmp.length; i++) {
                path = tmp[i] - 'a';
                if (node.nexts[path] == null) {
                    return 0;
                }
                node = node.nexts[path];
            }
            return node.end;
        }

        //树中有多少以str作为前缀的
        public int prefixNumber(String str) {
            if (str == null) {
                return 0;
            }

            Node node = root;
            char[] tmp = str.toCharArray();
            int path = 0;
            for (int i = 0; i < tmp.length; i++) {
                path = tmp[i] - 'a';
                if (node.nexts[path] == null) {
                    return 0;
                }
                node = node.nexts[path];
            }
            return node.pass;
        }

        //删除树中str字符串
        public void delete(String str) {
            //先确定要删除的字符串在树中存在,要不减完发现不存在就淦了
            if (search(str) != 0) {
                char[] tmp = str.toCharArray();
                Node node = root;
                node.pass--;
                int path = 0;
                for (int i = 0; i < tmp.length; i++) {
                    path = tmp[i] - 'a';
                    if (--node.nexts[path].pass == 0){
                        //避免内存泄漏,先--,如果是0,则后面的直接都干掉。
                        node.nexts[path] = null;
                        return;
                    }
                    node = node.nexts[path];
                }
                node.end--;
            }
        }
    }

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

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

相关文章

jQuery属性操作和内容文本值

1. 属性操作 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width,…

全局CSS样式1

1. 响应式基础 1.1 init <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compati…

chatgpt赋能python:Python两行三列列表:更高效的数据展示方式

Python 两行三列列表&#xff1a;更高效的数据展示方式 在Python编程中&#xff0c;经常会需要对数据进行展示。而最常见的方式则是使用列表。然而&#xff0c;当数据量较大时&#xff0c;传统的列表显示方式显得过于冗长。Python两行三列列表的使用&#xff0c;不仅可以增加代…

chatgpt赋能python:Python不挂科,学会这些技能就足够

Python不挂科&#xff0c;学会这些技能就足够 Python已成为现代编程语言中最受欢迎的一种&#xff0c;它擅长处理数据、人工智能等复杂的软件开发任务。互联网时代的到来也让Python的使用场景更加广泛&#xff0c;从前后端开发到数据分析。无论是学习Python的初学者还是有一定…

MQTT(3):MQTT协议原理

官方文档中对于MQTT协议包的结构有着具体的说明&#xff1a;http://mqtt.org/documentation 在MQTT协议中&#xff0c;一个MQTT数据包由&#xff1a;固定头&#xff08;Fixed header&#xff09;、可变头&#xff08;Variable header&#xff09;、消息体&#xff08;payload&…

chatgpt赋能python:介绍Python在SEO中的重要性

介绍Python在SEO中的重要性 随着互联网的不断发展&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;变得越来越重要。SEO一直是网络营销的重要组成部分&#xff0c;可以增加网站的可见性和流量。Python作为一种强大的编程语言&#xff0c;可以帮助网站优化人员更好地管理和…

LIMA和QLoRA论文解读

《LIMA: Less Is More for Alignment》 paper: https://arxiv.org/abs/2305.11206 Meta在2023年5月发布了论文《LIMA: Less Is More for Alignment》&#xff0c;基于LLaMa-65B微调了大模型LIMA&#xff0c;号称只用了1000个精心策划的问题和答复进行微调&#xff0c;就达到了…

HashMap 1.8全流程分析,详解put、resize、遍历等相关函数。以及其内部的二进制原理

简介 从常用属性->构造方法->添加->扩容->查询->删除->遍历的顺序进行HashMap源码阅读&#xff0c;涉及到一些二进制的用法以及意义也会进行说明。 HashMap源码解析 简介 HashMap采用了hash 表的数据结构进行实现&#xff0c;在key未存在hash冲突的情况下&…

Games104现代游戏引擎学习笔记09

Animation Blending 两个动画衔接 Math of blending&#xff1a;LERP&#xff1a;线性插值 在两个动画之间取关键帧插值 weight1weight2等于1 两个动画必须都是循环的&#xff0c;归一化之后能一致 Blend Space 在采用空间里的所有动画&#xff08;clips&#xff09;&#xf…

FastThreadLocal 原理解析

FastThreadLocal 每个 FastThread 包含一个 FastThreadLocalMap&#xff0c;每个 FastThreadLocalThread 中的多个 FastThreadLocal 占用不同的索引。每个 InternalThreadLocalMap 的第一个元素保存了所有的 ThreadLocal 对象。之后的元素保存了每个 ThreadLocal 对应的 value …

微服务架构之RPC调用

在单体应用时&#xff0c;一次服务调用发生在同一台机器上的同一个进程内部&#xff0c;也就是说调用发生在本机内部&#xff0c;因此也被叫作本地方法调用。在进行服务化拆分之后&#xff0c;服务提供者和服务消费者运行在两台不同物理机上的不同进程内&#xff0c;它们之间的…

Segment Anything——论文笔记

home page&#xff1a;segment-anything.com code&#xff1a;segment-anything 1. 概述 介绍&#xff1a;SAM是最近提出的一种通用分割大模型&#xff0c;其表现出了强大的零样本泛化能力&#xff0c;视觉感知模型的通用化又前进了一步。为了达到文章标题字面意义“segment a…

chatgpt赋能python:Python下载PyQt5教程

Python下载PyQt5教程 简介 PyQt5是一款Python编程语言的GUI框架&#xff0c;它基于QT库&#xff0c;专门用于开发图形界面应用程序。PyQt5可以实现跨平台开发&#xff0c;可在Windows&#xff0c;MacOS和Linux操作系统上运行。本文将介绍如何下载PyQt5&#xff0c;并在Python…

14、JavaEE--Mybatis注解与Ajax技术

目录 单表注解 Param注解 基于注解的一对一关联查询&#xff08;one&#xff09; 一对多查询&#xff08;many&#xff09; Ajax的概念 Ajax 开发 Ajax的核心代码: Ajax五步使用法 步骤1 创建 XMLHttpRequest 对象 步骤2 指定异步提交的目标和提交方式 步骤3 指定 X…

IT知识百科:什么是分布式云?

在当今信息技术高速发展的时代&#xff0c;云计算已经成为了企业和个人的重要组成部分。而在云计算领域中&#xff0c;分布式云是一种重要的架构模式&#xff0c;它允许资源的分散部署和管理&#xff0c;以实现高可用性、可伸缩性和弹性的服务提供。 本文将详细介绍什么是分布…

IT公司的吉祥“树” 二叉树-(堆)C语言创建

目录 &#x1f36a;前言 一、树概念及结构 ✅基本概念 ✅树的专有名词 ✅ 树的表示 &#x1f6a9;孩子兄弟表示法 二、二叉树概念及结构 ✅概念 &#x1f60d;&#x1f60d;现实中的二叉树&#xff08;又称IT公司的吉祥物&#xff09;&#x1f60d;&#x1f60d; ✅…

Nginx常用操作说明

Nginx常用操作说明 介绍Nginx概念深入浅出Nginx环境搭建Nginx反向代理-负载均衡Nginx动静分离Nginx动静分离先在部署Nginx的机器&#xff0c;Nginx目录下创建一个目录static_resources将项目中所有的静态资源全部拷贝到该目录下&#xff0c;而后将项目中的静态资源移除重新打包…

Hexo 个人博客主题美化

anzhiyu主题文档&#xff1a;https://anzhiy.cn/posts/220c.html anzhiyu主题插件地址&#xff1a;https://github.com/anzhiyu-c/hexo-theme-anzhiyu anzhiyu 主题安装 在博客根目录里执行命令&#xff0c;安装 anzhiyu 主题&#xff1a; git clone -b main https://github.co…

sql partition by和rank的统计用法

问题背景 最近公司有个项目需要用到某种特殊的统计用法&#xff0c; 例如从所有的数据中找出每个账号最新的一条余额信息&#xff08;根据某个关键信息进行排序并获取排序值最高的记录&#xff09;。 当时用的是非常普通的语句&#xff0c;也就是多个子查询嵌套select出每个账…

chatgpt赋能python:Python下载jieba:优化中文分词的必备工具

Python下载jieba&#xff1a;优化中文分词的必备工具 在中文自然语言处理的领域中&#xff0c;分词是一项基础且重要的任务。jieba是一个优秀的中文分词组件&#xff0c;它支持三种分词模式&#xff0c;并且具有高效、准确、易用等优点。本文将介绍如何通过Python来下载jieba&…