给出字符串,如“abc”
从头结点开始,依次检查,有没有走向a的路,如果没有,就新建出来,a作为路上的值(不是结点的值),如果有的话,就复用
在字符串的结尾处的结点的值+1,表示有一个是以该字符串结尾的
1.可以查是否某个字符串是以某个字符串为前缀的
2.还可以查 添加了几次该前缀 (有多少字符串是以该结点结尾的)
3.还可以查有多少个字符串是以字符串作为前缀的(前缀的词频是多少)(有多少字符串到达过该结点)
插入字符串:public void insert(String str)
删除字符串:public void delete(String str)
在前缀树中查询字符串出现的次数:public int search(String str)
在前缀树中查询以str字符串为前缀的个数:public int prefixNumber(String str)
public class TrieTree { //前缀树的结构 public static class TrieNode{ //表示扫过当前结点多少次 public int path; //表示以当前结点结尾的次数 public int end; //表示当前结点的下一个结点(从a-z) 同时,数组中对应的位置就是a-z字母的顺序 // 如果想表示其他类型的,可以使用HashMapnexts; // key表示的是边的ASCII码,value表示对应的下一个结点 public TrieNode[] nexts; public TrieNode(){ path = 0; end = 0; nexts = new TrieNode[26]; } } public static class Trie{ //前缀树的头结点 为空 private TrieNode root; public Trie(){ root = new TrieNode(); } /** * 将一个字符串加入前缀树,即向前缀树中添加路径和结点, * 首先检查前缀树中是否含有当前结点, * 如果存在的话,则将其路径上的path++,end++, * 如果不存在某几个结点的话,则创建出来 * @param str */ public void insert(String str){ if(str == null || str.length() == 0) return; char[] ch = str.toCharArray(); TrieNode trieNode = root; for(int i = 0; i < ch.length; i++){ int index = ch[i] - 'a'; //该元素不存在,则创建出来 if(trieNode.nexts[index] == null){ trieNode.nexts[index] = new TrieNode(); } trieNode = trieNode.nexts[index]; trieNode.path++; } trieNode.end++; } /** * 删除指定字符串对应在前缀树中的路径 * 在前缀树中查找,然后依次将其path-1, * 当path==0时,直接将其置为null即可(后面的结点都可以不要了) * @param str */ public void delete(String str){ if(str == null || str.length() == 0) return; char[] ch = str.toCharArray(); TrieNode trieNode = root; for(int i = 0; i < ch.length; i++){ int index = ch[i] - 'a'; if(--trieNode.nexts[index].path == 0){ trieNode.nexts[index] = null; return; } trieNode = trieNode.nexts[index]; } trieNode.end--; } /** * 查询一个字符串在前缀树中出现了多少次 * 如果一路下来都存在,则返回end中的值, * 如果过程中含有不存在的值,则返回0 * @param str * @return */ public int search(String str){ if(str == null || str.length() == 0) return 0; char[] ch = str.toCharArray(); TrieNode trieNode = root; for(int i = 0; i < ch.length; i++){ int index = ch[i] - 'a'; if(trieNode.nexts[index] == null) return 0; trieNode = trieNode.nexts[index]; } return trieNode.end; } /** * 查找以str为前缀的字符有多少 * 即查找以str为路径的path是多少 * @param str * @return */ public int prefixNumber(String str){ if(str == null || str.length() == 0) return 0; char[] ch = str.toCharArray(); TrieNode trieNode = root; for(int i = 0; i < ch.length; i++){ int index = ch[i] - 'a'; if(trieNode.nexts[index] == null) return 0; trieNode = trieNode.nexts[index]; } return trieNode.path; } public static void main(String[] args) { Trie trie = new Trie(); System.out.println(trie.search("zuo")); trie.insert("zuo"); System.out.println(trie.search("zuo")); trie.delete("zuo"); System.out.println(trie.search("zuo")); trie.insert("zuo"); trie.insert("zuo"); trie.delete("zuo"); System.out.println(trie.search("zuo")); trie.delete("zuo"); System.out.println(trie.search("zuo")); trie.insert("zuoa"); trie.insert("zuoac"); trie.insert("zuoab"); trie.insert("zuoad"); trie.delete("zuoa"); System.out.println(trie.search("zuoa")); System.out.println(trie.prefixNumber("zuo")); } }}