数据结构:字典树(前缀树,Trie树),压缩字典树(Radix)

字典树Trie Tree

字典树也称前缀树,Trie树。在 Elasticsearch 的倒排索引中用的也是 Trie 树。是一种针对字符串进行维护的数据结构。

字典树是对词典的一种存储方式,这个词典中的每个“单词”就是从根节点出发一直到某一个目标节点的路径,路径中每个字母连起来就是一个单词。因此它能利用字符串的公共前缀来节省存储空间。

在这里插入图片描述

红色代表有单词在这里结束,因此需要有个标记。上图可以匹配的字符串有:

a
bz
bd
bdjk
bg
ct
cu
dk

具体实现

package mainimport "fmt"type Node struct {nodeId int  // 节点的全局IDexist  bool // 是否有单词在这里结束
}// 256 表示每个节点最多有256个子节点,因为 ASCII 码目前是两个字节,
// 这样做会有一定的空间浪费,但是便于理解,也可以进一步优化。
type Nodes [256]Node// 每个子节点都是数组结构,最终存储到一个map中。
// 层层查找:nodeId -> indexId -> nodeId -> indexId ->...
type Tree struct {nodes         map[int]NodescurrentNodeId int // 自增ID
}func (tree *Tree) insert(str string) {var parentNode Nodefor i := 0; i < len(str); i++ {subIndex := str[i]if _, ok := tree.nodes[parentNode.nodeId]; !ok {var subNode Nodestree.nodes[parentNode.nodeId] = subNode}nds := tree.nodes[parentNode.nodeId]var needUpdate boolif nds[subIndex].nodeId == 0 {tree.currentNodeId++nds[subIndex].nodeId = tree.currentNodeIdneedUpdate = true}if i == len(str)-1 {nds[subIndex].exist = trueneedUpdate = true}if needUpdate == true {tree.nodes[parentNode.nodeId] = nds}// fmt.Println(string(subIndex), nds[subIndex]) // 调试输出parentNode = nds[subIndex]}
}func (tree *Tree) Exist(str string) bool {var parentNode Nodefor i := 0; i < len(str); i++ {subIndex := str[i]if _, ok := tree.nodes[parentNode.nodeId]; !ok {return false}nds := tree.nodes[parentNode.nodeId]if nds[subIndex].nodeId == 0 {return false}parentNode = nds[subIndex]}return parentNode.exist
}func main() {tree := &Tree{nodes: make(map[int]Nodes),}tree.insert("abcdefg")tree.insert("ab")tree.insert("123456789")tree.insert("123456")fmt.Println(tree.Exist("ab"))        // truefmt.Println(tree.Exist("abc"))       // falsefmt.Println(tree.Exist("123456789")) // truefmt.Println(tree.Exist("123456"))    // true
}
压缩字典树 Radix Tree

Radix树,即基数树,也称压缩字典树,是一种提供key-value存储查找的数据结构。radix tree常用于快速查找的场景中,例如:redis中存储slot对应的key信息、内核中使用radix tree管理数据结构、大多数http的router通过radix管理路由。Radix树在Trie Tree(字典树)的原理上优化过来的。

虽然Trie Tree具有比较高的查询效率,但是从上图可以看到,有许多结点只有一个子结点。这种情况是不必要的,不但影响了查询效率(增加了树的高度),主要是浪费了存储空间。完全可以将这些结点合并为一个结点,这就是Radix树的由来。Radix树将只有一个子节点的中间节点将被压缩,使之具有更加合理的内存使用和查询的效率。

在这里插入图片描述
在插入和删除节点时,Radix 与 Trie 相比,多了一个压缩和展开的过程,比如在上图的基础上插入db单词,那么现在的dk就要展开了。

在查询的时候,就可以一次比较多个字符,提高效率。

树状结构最大的问题是如果删除操作消耗比较大,所以通用的做法是采用标记删除,如果标记删除的节点比例达到10%就进行一次清理。

https://blog.csdn.net/qq_35423154/article/details/130119383

https://blog.csdn.net/penriver/article/details/121082106

https://blog.csdn.net/gz_hm/article/details/124814868

https://www.zhihu.com/question/30736334

https://zhuanlan.zhihu.com/p/533338300

patricia tree
crit-bit tree

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

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

相关文章

Ubuntu20.04安装向日葵、开机自启、解决windows系统远程黑屏(笔记)

这里写目录标题 动机1. Ubuntu20.04 安装向日葵2. 设置开机自启3. 解决windows不可远程的问题4. 大公告成 动机 办公室有个工作站&#xff0c;要比我的笔记本的CPU稍微好一点&#xff0c;用来跑陆面过程。我信心满满的装了个Ubuntu20.04双系统,但是发现向日葵安装不上了。我少…

面试必会-JAVA基础篇-02

文章目录 11. ArrayList 和 LinkedList 的区别是什么&#xff1f;12. 说一下HashMap的实现原理&#xff1f;13. HashMap的put方法的具体流程&#xff1f;14. 讲一讲HashMap的扩容机制15. ConcurrentHashMap 底层具体实现知道吗&#xff1f;16. 创建线程的四种方式17. runnable …

【C++ STL】vector类最全详解(什么是vector?vector类的常用接口有哪些?)

目录 一、前言 二、什么是vector ? &#x1f4a6; vector的基本概念 &#x1f4a6;vector的作用是什么 &#x1f4a6;总结 三、 vector的(一维)定义 四、vector(一维)常用接口的使用 &#x1f4a6;vector的常见构造&#xff08;初始化&#xff09; &#x1f4a6;vector…

python处理pdf中二维码图片,批量生成图片

比如一种pdf页面上有很多二维码&#xff0c;这些二维码比如是用于停车的&#xff0c;每次打开pdf截图或者其他模式存下来&#xff0c;然后扫码使用是不是感觉很麻烦&#xff0c;可以使用python把每个二维码生成图片&#xff0c;然后保存起来使用&#xff0c;当然想方便的话还可…

配置攻击防范示例

1、组网需求。 如果局域网内存在Hacker向SwitchA发起畸形报文攻击、分片报文攻击和泛洪攻击&#xff0c;将会造成SwitchA瘫痪。为了预防这种情况&#xff0c;管理员希望通过在SwitchA上部署各种攻击防范措施来为用户提供安全的网络环境&#xff0c;保障正常的网络服务。 2、配…

奥本海默-电影剧情简介

片头&#xff0c;奥本海默 脑海浮现恒星生命周期画面 1925年&#xff0c;奥本海默离开美国去欧洲学习新物理&#xff08;量子力学&#xff09; 脑海浮现量子力学相关画面&#xff08;像 德布罗意波&#xff09; 1927年从德国哥廷根大学毕业&#xff0c;获得物理学博士学位。…

ssm农业信息管理系统源码和论文

摘 要 网络的广泛应用给生活带来了十分的便利。所以把农业信息管理与现在网络相结合&#xff0c;利用java技术建设农业信息管理系统&#xff0c;实现农业信息管理的信息化。则对于进一步提高农业信息管理发展&#xff0c;丰富农业信息管理经验能起到不少的促进作用。 农业信息…

二极管:二极管的基本原理

一、认识导体、绝缘体、半导体 什么是导体&#xff1f; 导体 conductor &#xff0c;是指电阻率很小&#xff0c;且容易传导电流的物质。导体中存在大量可自由移动的带电粒子&#xff0c;也称为载流子。在外电场的作用下&#xff0c;载流子作定向运动&#xff0c;形成电流。 …

【Linux】进程控制--进程创建/进程终止/进程等待/进程程序替换/简易shell实现

文章目录 一、进程创建1.fork函数2.fork函数返回值3.写时拷贝4.fork常规用法5.fork调用失败的原因 二、进程终止1.进程退出码2.进程退出场景3.进程常见退出方法 三、进程等待1.为什么要进行进程等待2.如何进行进程等待1.wait方法2.waitpid方法3.获取子进程status4.进程的阻塞等…

Nginx 简单入门操作

前言:之前的文章有些过就不罗嗦了。 Nginx 基础内容 是什么? Nginx 是一个轻量级的 HTTP 服务器,采用事件驱动、异步非阻塞处理方式的服务器,它具有极好的 IO 性能,常用于 HTTP服务器(包含动静分离)、正向代理、反向代理、负载均衡 等等. Nginx 和 Node.js 在很多方…

Android Studio的笔记--String和byte[]

String和byte[]的相互转换&#xff0c;字节数组转换 String转换byte[]文本16进制字节数组 byte[]转换String文本16进制 其它 String转换byte[] 文本 将字符串&#xff08;String&#xff09;转换为字节&#xff08;byte&#xff09;的方法。默认使用的是UTF-8编码 StandardCh…

全屏显示功能

全屏显示功能 screenfull 依赖下载 yarn add screenfull --save-dev使用 <template><!-- 全屏的字体图标 --><header><i class"iconfont icon-quanping"> </i></header> </template> <script> import screenfull …