由簡入繁--Trie樹實戰
You only get one shot, do not miss your chance to blow.
引言
trie樹又稱“字典樹”。關鍵詞提示功能在日常生活中非常常用,通常只需要輸出字首,它就會給出相應的提示。呢具體是怎麼實現的呢?本文主要分享了基於trie樹的一個簡易的搜尋提示以及trie樹常用的應用場景。所有原始碼均已上傳至github: 連結
ps:Trie 樹的本質,就是利用字串之間的公共字首,將重複的前綴合並在一起。
模擬搜尋關鍵詞提示功能
本次實現其實也可以改造一下,將使用者習慣(輸入內容)存成一顆trie樹
以how,hi,her,hello,so,see為例
宣告一個tire類
這裡偷了個小懶,整了一個內部類。
public class TrieNode { /** * 字元 */ public char data; /** * 子節點 */ TrieNode[] children; /** * 標識 */ boolean isEndingChar; TrieNode(char data) { children = new TrieNode[26]; isEndingChar = false; this.data = data; } }複製程式碼
初始化
通常根節點是不儲存任何資訊的,起一個佔位符的作用
/** * 根節點 */ private TrieNode root; /** * 預製單詞數量 */ private int count; /** * 提示詞列表 */ private List<String> list; /** * 輸入值 */ private String pattern; /** * 儲存一個無意義的字元 */ private TrieTree() { root = new TrieNode('/'); count = 0; list = new ArrayList<>(); }複製程式碼
插入
private void insert(char[] txt) { TrieNode p = root; for (char c : txt) { //當前字元的ASCII碼 - 'a'的 ASCII碼 int index = c - 'a'; if (null == p.children[index]) { TrieNode node = new TrieNode(c); p.children[index] = node; } p = p.children[index]; } ++count; p.isEndingChar = true; }複製程式碼
查詢
private boolean contains(String pattern) { char[] patChars = pattern.toCharArray(); TrieNode p = root; for (char patChar : patChars) { int index = patChar - 'a'; if (null == p.children[index]) return false; p = p.children[index]; } return p.isEndingChar; }複製程式碼
模糊提示匹配
private void match() { char[] patChars = pattern.toCharArray(); TrieNode p = root; for (char patChar : patChars) { int index = patChar - 'a'; if (null == p.children[index]) return; p = p.children[index]; } //開始遍歷 p,將所有匹配的字元加入strs traversal(p, ""); }複製程式碼
遞迴遍歷節點
private void traversal(TrieNode trieNode, String str) { if (null != trieNode) { str += trieNode.data; if (trieNode.isEndingChar) { String curStr = pattern.length() == 1 ? str : pattern + str.substring(pattern.length() - 1); if (!list.contains(curStr)) list.add(curStr); return; } for (int i = 0; i < trieNode.children.length; i++) { traversal(trieNode.children[i], str); } } }複製程式碼
測試程式碼
人為構造一個tire樹
ps:這裡的儲存會導致樹很高,比如 l l o,其實可以合成llo,也就是縮點優化。這裡暫時不實現了。
private void initTries() { //how,hi,her,hello,so,see /// //hs //eiooe //lwe //l //o char[] how = "how".toCharArray(); insert(how); char[] hi = "hi".toCharArray(); insert(hi); char[] her = "her".toCharArray(); insert(her); char[] hello = "hello".toCharArray(); insert(hello); char[] so = "so".toCharArray(); insert(so); char[] see = "see".toCharArray(); insert(see); }複製程式碼
測試程式碼
public static void main(String[] args) { TrieTree trieTree = new TrieTree(); trieTree.initTries(); String str = "hello"; boolean res = trieTree.contains(str); System.out.println("trie樹是否包含" + str + "返回結果:" + res); trieTree.pattern = "h"; trieTree.match(); System.out.println("單字元模糊匹配 " + trieTree.pattern + ":"); trieTree.printAll(); trieTree.list.clear(); trieTree.pattern = "he"; trieTree.match(); System.out.println("多字元模糊匹配 " + trieTree.pattern + ":"); trieTree.printAll(); }複製程式碼
測試結果
trie樹實戰
未完待續...
end
您的點贊和關注是對我最大的支援,謝謝!