# leetcode:實現 Trie (前綴樹)

### 題目描述:

=============================================================

Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // 返回 true
trie.search(“app”); // 返回 false
trie.startsWith(“app”); // 返回 true
trie.insert(“app”);
trie.search(“app”); // 返回 true
=============================================================

### java算法實現

#### R向單詞查找樹:

``````//由於僅包含小寫字母，因此考慮使用Ｒ向單詞查找樹結構

class Trie {
private Node root;
class Node{
boolean isEnd; //標記當前節點是否是某一字符串的結尾.(由結尾字符鏈接指向)
Node[] next = new Node[26];
}

/** Initialize your data structure here. */
public Trie() {
}

//將最後一個節點的isEnd設置爲True
private Node insert(Node x, String word, int d){
if(x == null){ //如果當前節點爲空,則新創建一個節點.
x = new Node();
}

if(d == word.length()){ //如果已經插入了d個字符,則當前節點isEnd爲true
x.isEnd = true;
return x;
}
else
//添加指向第d個字符鏈接,即表示插入第d個字符
x.next[word.charAt(d)-'a'] = insert(x.next[word.charAt(d)-'a'], word, d+1);
return x;
}

/** Inserts a word into the trie. */
public void insert(String word) {
root = insert(root, word, 0);
}

private boolean search(Node x, String word, int d){
if(x == null) //如果當前節點爲null,非空字符串word不在前綴樹中.
return false;
//如果x不爲空,則word.charAt(d-1)存在
if(d == word.length()){
//如果d==word.length(), 則當前字符串的所有字符均已判斷,判斷當前節點是否是結尾字符
return x.isEnd;
}
else
//判斷word.charAt(d)
return search(x.next[word.charAt(d)-'a'], word, d+1);
}

/** Returns if the word is in the trie. */
public boolean search(String word) {
return search(root, word, 0);
}

//startsWith思路與search一致,只不過對於startsWith無需判斷最後一個節點是否是結尾字符,只要當前前綴樹中能夠搜索到prefix即返回true
private boolean startsWith(Node x, String prefix, int d){
if(x == null)
return false;
if(d == prefix.length())
return true;
else
return startsWith(x.next[prefix.charAt(d)-'a'], prefix, d+1);
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
return startsWith(root, prefix, 0);
}
}
``````

#### 三向查找樹

``````//三向單詞查找樹

class Trie {
private Node root;

class Node{
private boolean isEnd;
private char c; //保存當前節點對應的字符
private Node left; //指向小於當前字符c的節點鏈接
private Node mid; //指向等於字符c的節點鏈接
private Node right; //指向大於字符c的節點鏈接
Node(char c, Node left, Node mid, Node right){
this.c = c;
this.left = left;
this.mid = mid;
this.right = right;
}
}

/** Initialize your data structure here. */
public Trie() {
}

private Node insert(Node x, String word, int d){
if(x == null){
x = new Node(word.charAt(d), null, null, null);
}

if(word.charAt(d) > x.c){
x.right = insert(x.right, word, d);
}
else if(word.charAt(d) < x.c){
x.left = insert(x.left, word, d);
}
else if(d < word.length()-1)
x.mid = insert(x.mid, word, d+1);
else //如果已經插入了所有d個字符,則當前節點爲結尾字符對應的節點
x.isEnd = true;
return x;
}
/** Inserts a word into the trie. */
public void insert(String word) {
root = insert(root, word, 0);
}

private boolean search(Node x, String word, int d){
if(x == null)
return false;
//判斷當前字符第d位
if(word.charAt(d) > x.c)
return search(x.right, word, d);
else if(word.charAt(d) < x.c)
return search(x.left, word, d);
else if(d < word.length() - 1)
return search(x.mid, word, d+1);
else
return x.isEnd;
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
return search(root, word, 0);
}

private boolean startsWith(Node x, String prefix, int d){
if(x == null)
return false;

if(prefix.charAt(d) > x.c)
return startsWith(x.right, prefix, d);
else if(prefix.charAt(d) < x.c)
return startsWith(x.left, prefix, d);
else if(d < prefix.length()-1)
return startsWith(x.mid, prefix, d+1);
else
return true;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
return startsWith(root, prefix, 0);
}
}

``````