首页 文章 精选 留言 我的

精选列表

搜索[压缩算法],共10000篇文章
优秀的个人博客,低调大师

《Java 数据结构与算法》第7章:字典树

持续坚持原创输出,点击蓝字关注我吧 作者:小傅哥博客:https://bugstack.cn ❝ 沉淀、分享、成长,让自己和他人都能有所收获!😜 ❞ 一、前言 二、字典树数据结构 三、字典树结构实现 1. 树枝节点 2. 插入元素 3. 索引元素 四、字典树功能测试 五、常见面试题 一、前言 Trie 的历史 字典树 Trie 这个词来自于 retrieval,于 1912 年,Axel Thue 首次抽象地描述了一组字符串数据结构的存放方式为 Trie 的想法。这个想法于 1960 年由 Edward Fredkin 独立描述,并创造了 Trie 一词。你看看,多少程序员为了一个词、方法名、属性名,想破脑袋! 二、字典树数据结构 在计算机科学中,字典树(Trie)也被称为”单词查找树“或”数字树“,有时候也被称为基数树或前缀树(因为可以通过前缀的方式进行索引)。—— 它是一种搜索树,一种已排序的数据结构,通常用于存储动态集或键为字符串的关联数组。 与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。 这是一个把 battle 单词字符串,按照字母拆分到字典树进行存放的图。 键标注在节点中,值标注在节点之下。每一个完整的英文单词对应一个特定的整数。也就是26个字母对应的 ASCII 转换后的值。 三、字典树结构实现 字典树字母的存放有26个,也就是说在实现的过程中,每一个节点的分支都有26个槽位用来存放可能出现的字母组合。同理如果是数字树的话就是10个数字的组合,每个字典树上的节点对应的分支则有10个操作存放可能出现组合的数字。 接下来我们就基于 Java 语言实现一个字典树的存放和遍历索引的功能。 源码地址:https://github.com/fuzhengwei/java-algorithms 本章源码:https://github.com/fuzhengwei/java-algorithms/tree/main/data-structures/src/main/java/stack 1. 树枝节点 publicclassTrieNode{/**形成一个链*/publicTrieNode[]slot=newTrieNode[26];/**字母*/publiccharc;/**单词:数量>0表示一个单词*/publicbooleanisWord;/**前缀*/publicintprefix;/**单词:具体的一个单词字符串*/publicStringword;/**解释:单词的注释说明*/publicStringexplain;} 字典的树的节点需要包括此节点内嵌的关联节点,之后是节点的字母、到此字母是否为单词、单词的前缀、单词字符串和当前单词的非必要注释。 2. 插入元素 publicvoidinsert(Stringwords,Stringexplain){TrieNoderoot=wordsTree;char[]chars=words.toCharArray();for(charc:chars){intidx=c-'a';//-a从0开始,参考ASCII码表if(root.slot[idx]==null){root.slot[idx]=newTrieNode();}root=root.slot[idx];root.c=c;root.prefix++;}root.explain=explain;//单词的注释说明信息root.isWord=true;//循环拆解单词后标记} insert 方法接收单词和注释信息,并对一个单词按照 char 进行拆分,拆分后则计算出索引位置并以此存放。存放完成后标记单词和附属上单词的注释信息。 3. 索引元素 publicList<String>searchPrefix(Stringprefix){TrieNoderoot=wordsTree;char[]chars=prefix.toCharArray();StringBuildercache=newStringBuilder();//精准匹配:根据前置精准查找for(charc:chars){intidx=c-'a';//匹配为空if(idx>root.slot.length||idx<0||root.slot[idx]==null){returnCollections.emptyList();}cache.append(c);root=root.slot[idx];}//模糊匹配:根据前缀的最后一个单词,递归遍历所有的单词ArrayList<String>list=newArrayList<>();if(root.prefix!=0){for(inti=0;i<root.slot.length;i++){if(root.slot[i]!=null){charc=(char)(i+'a');collect(root.slot[i],String.valueOf(cache)+c,list,15);if(list.size()>=15){returnlist;}}}}returnlist;}protectedvoidcollect(TrieNodetrieNode,Stringpre,List<String>queue,intresultLimit){//找到单词if(trieNode.isWord){trieNode.word=pre;//保存检索到的单词到queuequeue.add(trieNode.word+"->"+trieNode.explain);if(queue.size()>=resultLimit){return;}}//递归调用,查找单词for(inti=0;i<trieNode.slot.length;i++){charc=(char)('a'+i);if(trieNode.slot[i]!=null){collect(trieNode.slot[i],pre+c,queue,resultLimit);}}} 从字典树从检索元素的过程分为2部分,第1部分是根据提供的索引前缀精准匹配到单词信息,第2部分是根据索引前缀的最后一个单词开始,循环递归遍历从当前位置所能关联到的字母直至判断为是单词标记为结束,通过这样的方式把所有匹配动的单词索引出来。 list.size() >= 15 是判定索引的最大长度,超过这个数量就停止索引了,毕竟这是一种O(n)时间复杂度的操作,如果加载数十万单词进行匹配,执行速度还是比较耗时的。 四、字典树功能测试 @Testpublicvoidtest_trie(){Trietrie=newTrie();//存入trie.insert("bat","大厂");trie.insert("batch","批量");trie.insert("bitch","彪子");trie.insert("battle","战斗");logger.info(trie.toString());//检索List<String>trieNodes=trie.searchPrefix("ba");logger.info("测试结果:{}",JSON.toJSONString(trieNodes));} 这里提供一些有相近字母的单词和名词,用于测试。你也可以尝试读取txt文件,检索存入数十万单词进行检索验证。 测试结果 06:21:38.226[main] INFO trie.__test__.TrieTest -测试结果:["bat->大厂","batch->批量","battle->战斗"]Processfinishedwithexitcode0 通过测试结果可以看到,把所有以 ba 开头的单词全部检索出来了。这也是字典树最核心功能的体现。 读者在学习的过程中,可以尝试在检索的方法体内打一些断点看一下具体的执行过程,方便学习整个执行步骤。 五、常见面试题 简述字典树的数据结构 叙述你怎么来实现一个字典树 字典树的实际业务场景举例【排序、全文搜索、网络搜索引擎、生物信息】 字典树的存入和检索的时间复杂度 还有哪些字典树的实现方式【后缀树、哈希树、帽子树】 - END - 下方扫码关注 公众号【bugstack虫洞栈】回复【星球】,加入小傅哥的【私有技术朋友圈】你将获得;分布式DDD抽奖、API网关、IM通信、手写Mybatis、手写Spring、面经手册等高质量大厂项目和技术小册/PDF等资料。更多介绍 公众号:bugstack虫洞栈 你好,我是小傅哥。一线互联网 java 工程师、T8架构师,开发过交易&营销、写过运营&活动、设计过中间件也倒腾过中继器、IO板卡。不只是写Java语言,也搞过C#、PHP,是一个技术活跃的折腾者。 本文分享自微信公众号 - bugstack虫洞栈(bugstack)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册