Trie,又经常叫前缀树,字典树等等.实现思路如下
颜色为黑色的表示只是字符串中间的字符,为蓝色的表示是字符串末尾的那个字符,空白那个是树根节点.每个节点的意义实际上就是根,节点到这个结点所经过的每个字符组成的字符串.故而图中这个树实际上意味着已存在字符串"","to","tea","ted","ten","a","i","in","inn"
public class Trie { private int SIZE = 26; private TrieNode root;// 字典树的根 class TrieNode // 字典树节点 { private int num;// 有多少单词通过这个节点,即由根至该节点组成的字符串模式出现的次数 private TrieNode[] son;// 所有的儿子节点 private boolean isBlue;// 是不是最后字符 private char val;// 节点的值 TrieNode() { num = 1; son = new TrieNode[SIZE]; isBlue = false; } } Trie() // 初始化字典树 { root = new TrieNode(); } // 建立字典树 public void insert(String str) // 在字典树中插入一个单词 { if (str == null || str.length() == 0) { return; } TrieNode node = root; char[] letters = str.toCharArray();// 将目标单词转换为字符数组 for (int i = 0, len = str.length(); i < len; i++) { int pos = letters[i] - 'a'; if (node.son[pos] == null) // 如果当前节点的儿子节点中没有该字符,则构建一个TrieNode并复值该字符 { node.son[pos] = new TrieNode(); node.son[pos].val = letters[i]; } else // 如果已经存在,则将由根至该儿子节点组成的字符串模式出现的次数+1 { node.son[pos].num++; } node = node.son[pos]; } node.isBlue = true; } // 计算单词前缀的数量 public int countPrefix(String prefix) { if (prefix == null || prefix.length() == 0) { return -1; } TrieNode node = root; char[] letters = prefix.toCharArray(); for (int i = 0, len = prefix.length(); i < len; i++) { int pos = letters[i] - 'a'; if (node.son[pos] == null) { return 0; } else { node = node.son[pos]; } } return node.num; } // 在字典树中查找一个完全匹配的单词. public boolean has(String str) { if (str == null || str.length() == 0) { return false; } TrieNode node = root; char[] letters = str.toCharArray(); for (int i = 0, len = str.length(); i < len; i++) { int pos = letters[i] - 'a'; if (node.son[pos] != null) { node = node.son[pos]; } else { return false; } } // 走到这一步,表明可能完全匹配,可能部分匹配,如果最后一个字符节点为末端节点,则是完全匹配,否则是部分匹配 return node.isBlue; } public static void main(String[] args) { Trie tree = new Trie(); String[] dictionaryData = { "hello", "student", "computer", "sorry", "acm", "people", "experienced", "who", "reminds", "everyday", "almost" }; String[] txt = { "computer", "hello", "acm", "computer", "experienced", "computer", "hello", "eclipse", "student", "hello", "hello", "hello", "hello", "experienced" }; // 构建字典 for (String str : dictionaryData) { tree.insert(str); } Map<String, Integer> countMap = new HashMap<String, Integer>(); for (int i = 0; i < txt.length; i++) { String lineTxt = txt[i]; if (tree.has(lineTxt)) { if (countMap.containsKey(lineTxt)) { countMap.put(lineTxt, countMap.get(lineTxt) + 1); } else { countMap.put(lineTxt, 1); } } else { System.out.println(lineTxt + "不在字典中!"); } } for (String s : countMap.keySet()) { System.out.println(s + "出现的次数" + countMap.get(s)); } } }
1.字符串检索
事先将已知的一些字符串(字典)的有关信息保存到trie树里,查找另外一些未知字符串是否出现过或者出现频率。
2.词频统计
有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
3.排序
Trie树是一棵多叉树,只要先序遍历整棵树,输出相应的字符串便是按字典序排序的结果。
4.字符串最长公共前缀
5.字符串搜索的前缀匹配
trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。