Java實現單詞樹(trie)
阿新 • • 發佈:2018-11-12
package com.shundong.utils; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 一個只能處理26個字母的單詞樹(trie) * 空間換時間 T(n) = O(n) * ps:如果缺陷 歡迎留言 * @author shundong * @data 2018-10-13 */ public class FindWordsTrie{ //一個Trie樹有一個根節點 private Vertex root; //內部類or節點類 protected class Vertex{ protected int words; protected int prefixes; //每個節點包含26個子節點(型別為自身) protected Vertex[] edges; Vertex() { words = 0; prefixes = 0; edges = new Vertex[26]; for (int i = 0; i < edges.length; i++) { edges[i] = null; } } } public FindWordsTrie () { root = new Vertex(); } /** * 列出List所有單詞 * @return */ public List< String> listAllWords() { List< String> words = new ArrayList< String>(); Vertex[] edges = root.edges; for (int i = 0; i < edges.length; i++) { if (edges[i] != null) { String word = "" + (char)('a' + i); depthFirstSearchWords(words, edges[i], word); } } return words; } /** * Depth First在Trie中搜索單詞並將它們新增到List中。 * @param words * @param vertex * @param wordSegment */ private void depthFirstSearchWords(List words, Vertex vertex, String wordSegment) { Vertex[] edges = vertex.edges; boolean hasChildren = false; for (int i = 0; i < edges.length; i++) { if (edges[i] != null) { hasChildren = true; String newWord = wordSegment + (char)('a' + i); depthFirstSearchWords(words, edges[i], newWord); } } if (!hasChildren) { words.add(wordSegment); } } public int countPrefixes(String prefix) { return countPrefixes(root, prefix); } private int countPrefixes(Vertex vertex, String prefixSegment) { if (prefixSegment.length() == 0) { //到達單詞的最後一個字元 return vertex.prefixes; } char c = prefixSegment.charAt(0); int index = c - 'a'; if (vertex.edges[index] == null) { // 這個詞不存在 return 0; } else { return countPrefixes(vertex.edges[index], prefixSegment.substring(1)); } } public int countWords(String word) { return countWords(root, word); } private int countWords(Vertex vertex, String wordSegment) { if (wordSegment.length() == 0) { //到達單詞的最後一個字元 return vertex.words; } char c = wordSegment.charAt(0); int index = c - 'a'; if (vertex.edges[index] == null) { // 這個詞不存在 return 0; } else { return countWords(vertex.edges[index], wordSegment.substring(1)); } } /** * 在Trie上新增一個單詞 * @param word 要新增的詞 */ public void addWord(String word) { addWord(root, word); } /** * 新增指定頂點的單詞 * @param vertex 指定的頂點 * @param word 要新增的詞 */ private void addWord(Vertex vertex, String word) { if (word.length() == 0) { //如果已新增該單詞的所有字元 vertex.words ++; } else { vertex.prefixes ++; char c = word.charAt(0); c = Character.toLowerCase(c); int index = c - 'a'; if (vertex.edges[index] == null) { //如果邊緣不存在 vertex.edges[index] = new Vertex(); } addWord(vertex.edges[index], word.substring(1)); //去下一個 } } //簡單的測試測試 public static void main(String args[]) { FindWordsTrie trie = new FindWordsTrie(); trie.addWord("cabbage"); trie.addWord("cabbage"); trie.addWord("cabbage"); trie.addWord("cabbage"); trie.addWord("cabin"); trie.addWord("berte"); trie.addWord("cabbage"); trie.addWord("english"); trie.addWord("establish"); trie.addWord("good"); // System.out.println(trie.root.prefixes); // System.out.println(trie.root.words); // List< String> list = trie.listAllWords(); // Iterator listiterator = list.listIterator(); // //遍歷 // while(listiterator.hasNext()) // { // String str = (String)listiterator.next(); // System.out.println(str); // } int count = trie.countPrefixes("c");//此處傳參 int count1=trie.countWords("cabbage"); System.err.println("單詞c 字首個數為:"+count); System.err.println("cabbage 單詞的個數為:"+count1); } }