我在嘗試製作文本自動完成模塊時遇到此問題。我通過創建一個Trie來解決這個問題,其中每個節點都包含它的父節點以及子節點。首先,我搜索從輸入前綴開始的節點。然後我在Trie上應用遍歷,探索子樹的所有節點,並將其根作爲前綴節點。每遇到葉節點,就意味着已經找到從輸入前綴開始的單詞的結尾。從該葉節點開始,迭代父節點的父節點,併到達子樹的根。在這樣做的時候,我一直在堆棧中添加節點的密鑰。最後我拿到了前綴,並通過彈出堆棧開始附加它。我一直保存在一個ArrayList中的單詞。在遍歷結束時,我得到從輸入前綴開始的所有單詞。下面是使用示例代碼:
class TrieNode
{
char c;
TrieNode parent;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
public TrieNode(char c){this.c = c;}
}
-
public class Trie
{
private TrieNode root;
ArrayList<String> words;
TrieNode prefixRoot;
String curPrefix;
public Trie()
{
root = new TrieNode();
words = new ArrayList<String>();
}
// Inserts a word into the trie.
public void insert(String word)
{
HashMap<Character, TrieNode> children = root.children;
TrieNode crntparent;
crntparent = root;
//cur children parent = root
for(int i=0; i<word.length(); i++)
{
char c = word.charAt(i);
TrieNode t;
if(children.containsKey(c)){ t = children.get(c);}
else
{
t = new TrieNode(c);
t.parent = crntparent;
children.put(c, t);
}
children = t.children;
crntparent = t;
//set leaf node
if(i==word.length()-1)
t.isLeaf = true;
}
}
// Returns if the word is in the trie.
public boolean search(String word)
{
TrieNode t = searchNode(word);
if(t != null && t.isLeaf){return true;}
else{return false;}
}
// Returns if there is any word in the trie
// that starts with the given prefix.
public boolean startsWith(String prefix)
{
if(searchNode(prefix) == null) {return false;}
else{return true;}
}
public TrieNode searchNode(String str)
{
Map<Character, TrieNode> children = root.children;
TrieNode t = null;
for(int i=0; i<str.length(); i++)
{
char c = str.charAt(i);
if(children.containsKey(c))
{
t = children.get(c);
children = t.children;
}
else{return null;}
}
prefixRoot = t;
curPrefix = str;
words.clear();
return t;
}
///////////////////////////
void wordsFinderTraversal(TrieNode node, int offset)
{
// print(node, offset);
if(node.isLeaf==true)
{
//println("leaf node found");
TrieNode altair;
altair = node;
Stack<String> hstack = new Stack<String>();
while(altair != prefixRoot)
{
//println(altair.c);
hstack.push(Character.toString(altair.c));
altair = altair.parent;
}
String wrd = curPrefix;
while(hstack.empty()==false)
{
wrd = wrd + hstack.pop();
}
//println(wrd);
words.add(wrd);
}
Set<Character> kset = node.children.keySet();
//println(node.c); println(node.isLeaf);println(kset);
Iterator itr = kset.iterator();
ArrayList<Character> aloc = new ArrayList<Character>();
while(itr.hasNext())
{
Character ch = (Character)itr.next();
aloc.add(ch);
//println(ch);
}
// here you can play with the order of the children
for(int i=0;i<aloc.size();i++)
{
wordsFinderTraversal(node.children.get(aloc.get(i)), offset + 2);
}
}
void displayFoundWords()
{
println("_______________");
for(int i=0;i<words.size();i++)
{
println(words.get(i));
}
println("________________");
}
}//
例
Trie prefixTree;
prefixTree = new Trie();
prefixTree.insert("GOING");
prefixTree.insert("GONG");
prefixTree.insert("PAKISTAN");
prefixTree.insert("SHANGHAI");
prefixTree.insert("GONDAL");
prefixTree.insert("GODAY");
prefixTree.insert("GODZILLA");
if(prefixTree.startsWith("GO")==true)
{
TrieNode tn = prefixTree.searchNode("GO");
prefixTree.wordsFinderTraversal(tn,0);
prefixTree.displayFoundWords();
}
if(prefixTree.startsWith("GOD")==true)
{
TrieNode tn = prefixTree.searchNode("GOD");
prefixTree.wordsFinderTraversal(tn,0);
prefixTree.displayFoundWords();
}
這將有助於您定義*什麼*部分不工作;考慮說出輸入和預期輸出是什麼,然後向我們展示實際輸出。 – 2010-05-08 14:20:58
這並不是說上面的代碼不工作,它可以正常工作,它是通知是否在字典中找到該字符串......我想要做什麼,會例如爲用戶輸入「th」,並且對於上面的方法(修改)來返回從trie中以「th」開始的所有單詞。 – user330572 2010-05-08 14:32:55
作業,也樹? – Woot4Moo 2010-05-08 14:37:23