当前位置: 首页 > 后端技术 > Java

前缀树

时间:2023-04-01 17:34:14 Java

1.前缀树的定义1)单个字符串中,字符从前到后加入多叉树2)字符放在边上,节点上有独占数据项(常见的传值和端值)3)示例添加方法,每个字符串从根节点开始添加,如果没有路径则创建,如果有路径则重复使用节点的结束值加1的函数:更方便完成前缀2相关的查询,简化的前缀树只能存储26个小写字母组成的字符串/***字符类型:只有26个小写字母**@authorJava与算法学习:周一*/publicstaticclassNode1{//当前节点被传递了多少次privateintpass;//有多少个字符串以当前节点结尾privateintend;//当前节点的所有子节点privateNode1[]nexts;//节点只存储26个小写字母publicNode1(){pass=0;结束=0;//node[i]==null,节点不存在nexts=newNode1[26];}}publicstaticclassTrie1{privateNode1root;publicTrie1(){root=newNode1();}/***添加一个字符串到前缀树中*/publicvoidinsert(Stringword){==ifnull(word/Upperchar[]chars=word.toCharArray();for(charaChar:chars){//当前字符应该走的路径path=aChar-'a';//如果当前节点路径对应的节点不存在,则新建一个if(node.nexts[path]==null.node){nexts[path]=newNode1();}//当前节点的路径path对应的节点必须已经存在//所以当前节点来到路径path对应的节点node=node.nexts[path];//字符已经到达该节点,修改pass值node.pass++;}}//添加字符后,修改最后一个节点的结束值node.end++;}/***单词word之前添加了多少次*/publicintsearch(Stringword){if(word==null){return0;}intindex=0;char[]chars=word.tochararray();//开始寻找node1node1node=root;for(charachars){//当前字符应该走的路径index=aChar-'a';//当前节点的索引路径对应一个不存在的节点,直接返回if(node.nexts[index]==null){nodeofexreturnind0;/}如果路径对应的节点存在,则当前搜索节点来到索引路径对应的节点node=node.nexts[索引];}}//当前节点的最后一个结束值是该词被添加的次数returnnode.end;}/***在所有添加的字符串中,有多少是pre前缀*/publicintprefixnumber(stringpre){if(pre==null){return0;}intindex=0;//开始寻找node1node=root;//一个一个地查找charts=pre.tocharray。();for(charaChar:chars){//当前字符应该走的路径index=aChar-'a';//当前节点的index路径对应的节点不存在,直接返回if(node.nexts[index]==null){return0;}}//当前节点的索引路径对应的节点存在,则当前搜索节点来到索引路径对应的节点node=node.nexts[index];值为prereturnnode.pass前缀的数字;}/***删除前缀树中的一个字符串*/publicvoiddelete(Stringword){//只有该字符串存在才执行删除逻辑if(search(word)!=0){//从根节点开始Node1节点=根;//修改根节点的pass值node.pass--;整数索引=0;char[]chars=word.tochararray();for(charachars){//当前字符应该走的路径index=achar-'a';//当前节点该节点对应的节点Pass的通行证。将值减一if(--node.nexts[index].pass==0){//如果减一后为0,则表示没有字符串经过该节点//清除对应的节点本节点索引路径帮助Gcnode.nexts[Index]=NULL;return;}//减一后不为0,说明有字符串经过该节点//当前节点移动到索引路径nodenode=node.nexts[index];}以及算法学习:Monday*/publicstaticclassNode2{//当前节点已经传了几次privateintpass;//有多少个字符串以当前节点结尾privateintend;//当前节点的所有子节点,Key节点对应的字符串转换为整数后的ASCII码值privateHashMapnexts;publicNode2(){pass=0;结束=0;nexts=newHashMap<>();}}publicstaticclassTrie2{privateNode2root;publicTrie2(){root=newNode2();}/***向前缀树中添加一个字符串,这个字符串不必全是小写字母*/publicvoidinsert(Stringstr){if(str==null){return;}}//添加字符串的节点Node2node=root;传递值node.pass++;整数索引=0;//当前字符串逐个字符添加到前缀树中char[]chars=str.toCharArray();for(charaChar:chars){/index/=aChar;如果该节点的index路径对应的节点不存在,则新建一个if(!node.nexts.containsKey(index)){node.nexts.put(index,newNode2());}//当前节点的索引路径对应的节点已经存在了//所以当前节点来到索引路径对应的节点node=node.nexts.get(index);//部分字符已经到达节点,修改pass值node.pass++;}}//添加字符串后,修改最后一个节点结束值node.end++;}/***该字符串之前添加了多少次*/publicintseArch(stringstr){if(str==null){return0;}intindex=0;char[]chars=str.tocharray();//开始寻找node2node=root;:Chars){//当前字符应该走的路径index=AChar;//当前节点对应节点的INDEX路径不存在,直接返回if(!Node.nexts.containskey(INDEX)){Return0;}//当前如果节点索引路径对应的节点存在,当前搜索节点来到索引路径对应的节点node=node.nexts.get(index);}}//最后一个当前节点的结束值为该字符串被添加的次数returnnode.结尾;}/***在所有添加的字符串中,有多少是pre前缀*/publicintprefixNumber(Stringpre){if(pre==null){return0;}}=int0index//从根节点开始查找Node2node=root;//一个一个地查找字符char[]chars=pre.toCharArray();for(charaChar:chars){//当前字符应该走的路径//CharArray;index=当前节点的index路径对应的节点不存在,直接返回if(!node.nexts.containsKey(index)){返回0;//当前节点的最后一个pass值为prereturnnode.pass前缀的数字;}/***删除前缀树中的一个字符串*/publicvoiddelete(Stringstr){//字符串存在只执行删除逻辑if(search(str)!=0){//从根节点node2开始节点=根;//修改根节点传值node.pass-;整数索引=0;字符[]字符=str.toCharArray();for(charaChar:chars){//当前字符应该走的路径index=aChar;//当前节点的index路径对应的节点的pass值减一ext(.get.nodesext..Pass==0){//如果为0,如果为0,表示在传递本节点索引路径对应节点空node.nexts.remove(index)之前没有字符串传递本节点;return;}//minusminusreduction1后不为0,说明还有字符串经过这个节点//然后当前节点移动到索引路径对应的节点node=node.nexts.get(index);}}//最后修改节点位置的结束值node.end--;最基础的功能,在实际项目中遇到类似需求时,可以在此基础上添加需要的功能,相当于提供了模板。从Github获取本文所有代码

猜你喜欢