前缀树用来解决这样的问题:
有数组[“a”,”abc”,”abc”,”abcd”,”bcd”,”hello”] , 求整个数组中abc的个数或者以**ab**为前缀的单词的个数?
尽管通过遍历,然后对每一个单词进行逻辑判断也能够实现,但是时间复杂度过高,前缀树可以以O(logn)的复杂度完成单词的计数和前缀的计数。
结构实现
前缀树中,元素位于节点和节点之间的树枝上,在前缀树中查找任何一个元素或者前缀都只需要O(logn)。
//前缀树结构public class Tire {//前缀树的根节点public TreeNode root;//前缀树的元素个数public int size;public Tire() {this.root = new TreeNode();this.size = 0;}//在前缀树中插入元素public int insert(String word) {if (null == word) {return size;}char[] chars = word.toCharArray();//根节点+1,表示多了一个元素this.root.pass++;//元素数+1this.size++;//如果是空字符串,就说明以头节点为结尾的元素+1if (chars.length == 0) {this.root.end++;return size;}TireNode node = root;for (char c : chars) {if (node.nexts.get(c) == null) {//如果没有这个字符,就新建node.nexts.put(c) = new TireNode();}node = node.nexts.get(c);node.pass++;}node.end++;return size;}//在前缀树中查询单词的个数public int search(String word) {if (null == word) {return 0;}char[] chars = word.toCharArray();TireNode node = root;for (char c : chars) {//如果没有遍历完全chars,就说明没有这个单词if (!node.nexts.containsKey(c)) {return 0;}node = node.nexts.get(c);}return node.end;}//在前缀树中查找以prefix为前缀的单词的个数public int searchPrefix(String prefix) {if (null == prefix) {return 0;}char[] chars = word.toCharArray();TireNode node = root;for (char c : chars) {if (!node.nexts.containsKey(c)) {return 0;}node = node.nexts.get(c);}return node.pass;}//从前缀树中删除元素public int delete(String word) {if (null == word || search(word) == 0) {return 0;}char[] chars = word.toCharArray();TireNode node = root;//头节点pass--,代表少了一个wordnode.pass--;size--;for (char c : chars) {if (--node.nexts.get(c).pass == 0) {//要是直接删除没了,那就直接把这一条路径设置为nullnode.nexts.remove(c);return size;}node = node.nexts.get(c);}node.end--;return size;}}//前缀树中节点的结构class TreeNode {//通过该节点的元素个数public int pass;//以该节点结尾的元素个数public int end;//节点的下属节点(即字符串的下一个字符)public HashMap<Character,TreeNode>();public TreeNode() {this.pass = 0;this.end = 0;this.nexts = new HashMap<>();}}
