Trie/字典树/前缀树-代码实现
一、什么是Trie?
字典:如果有n个条目,使用树结构,查询的时间复杂度为O(logn),如果有100万个条目(2^20)logn大约为20;
Trie:查询每个条目的时间复杂度和字典中一共有多少条目无关!时间复杂度为O(w),w为字符串的长度。
Trie结构图:把字符串存成一个一个的字符,形成一颗多叉树。——只存储字符串
二、Trie的实现-字典树
使用代码实现Trie:isword代表此节点指的是不是一个单词,next 使用Java 提供的映射进行实现,代表指示的节点。
public class Trie { private class Node{ // 是否是单词 public boolean isWord; // 演示中只考虑Character对象,不使用泛型 public TreeMap<Character,Node> next; public Node(boolean isWord){ this.isWord = isWord; new TreeMap<>(); } public Node(){ this(false); } } public Node root; // 存储了多少个元素 public int size; public Trie(){ root = new Node(); size = 0; } // 获取trie中存储的单词数量 public int getSize(){ return size; } // 向Trie中添加一个新的单词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++; } } // 查询单词word是否在Trie中 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 true; return cur.isWord; } }
三、Trie和前缀搜索
代码实现逻辑:
// 查询是否在Trie中有单词以prefix为前缀 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; }