trie 字典树 前缀树
-
又称为单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串,所以经常被搜索引擎系统用于文本词频统计。优点是:利用字符串的公共前缀来减少查询时间,最大限度的减少无谓的字符串比较,查询效率比哈希树高
-
根节点不包含字符,除根节点外每一个节点都只包含一个字符; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同
-
注意:对于Trie来说,其实还有一个重要的时间开销。由于Trie消耗的空间比较大(每个节点会有若干个指针),所以给这些承载指针的空间(TreeMap,HashMap或者数组)开辟内存也是一个额外的时间消耗
-
节点进行包装:
private class Node{ public boolean isWord; public TreeMap<Character,Node> next; public Node(boolean isWord) { this.isWord = isWord; next = new TreeMap<>(); } public Node() { this(false); } }
-
添加:
//向树中添加一个新的单词word public void add(String word) { Node cur = root; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); if(cur.next.get(c)==null) { cur.next.put(c,new Node()); } cur = cur.next.get(c); } if(!cur.isWord){ cur.isWord = true; size++; } }
-
包含
//查询单词是否存在在树中 public boolean contains(String word){ Node cur = root; for (int i = 0; i <word.length() ; i++) { char c = word.charAt(i); if(cur.next.get(c)==null) return false; cur = cur.next.get(c); } return cur.isWord; }
-
前缀搜索
//前缀搜索 public boolean isPrefix(String prefix) { Node cur = root; for (int i = 0; i < prefix.length(); i++) { char c = prefix.charAt(i); if(cur.next.get(c) == null) return false; cur = cur.next.get(c); } return true; }
-
总体代码
package 数据结构.Trie; import jdk.nashorn.api.tree.ReturnTree; import java.util.TreeMap; public class Trie { private class Node{ public boolean isWord; public TreeMap<Character,Node> next; public Node(boolean isWord) { this.isWord = isWord; next = new TreeMap<>(); } public Node() { this(false); } } private Node root; private int size; public Trie(){ root = new Node(); size = 0; } //获得树中单词数量 public int getSize() { return size; } //向树中添加一个新的单词word public void add(String word) { Node cur = root; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); if(cur.next.get(c)==null) { cur.next.put(c,new Node()); } cur = cur.next.get(c); } if(!cur.isWord){ cur.isWord = true; size++; } } //查询单词是否存在在树中 public boolean contains(String word){ Node cur = root; for (int i = 0; i <word.length() ; i++) { char c = word.charAt(i); if(cur.next.get(c)==null) return false; cur = cur.next.get(c); } return cur.isWord; } //前缀搜索 public boolean isPrefix(String prefix) { Node cur = root; for (int i = 0; i < prefix.length(); i++) { char c = prefix.charAt(i); if(cur.next.get(c) == null) return false; cur = cur.next.get(c); } return true; } }