TRIE的结构实现千种万种,网上到处都有,这里介绍的仅仅是我写的一种。
首先,建立一个Node,里面存有指针,原始设定为256个,可以根据要求进行缩短;另外还有key,value,分别是string和泛型,Trie作为字符串处理的工具,把key设为string类型很正常,value是作为附加变量方便使用。
再者,就是Trie的类了,下面代码提供了递归和非递归的add(key, value), get(key)方法,和BST一样,非递归方法写起来顺手,而递归方法代码清晰,结构明了,可能不太容易想到;另外还有contains(key), containPart(str)方法,提供判断字符串在trie中的具体情况;并没有remove方法,但是,要做到只删除value的remove()方法,还是超出想象的容易的。
最后,还有一个面试题,这个代码是放在TRIE结构中的,适用场景是:已知所有出现过的字符串已经被存入TRIE中,当重新搜索字符串时,每次输入一个字符的时候,返回这个字符所衍生的所有记录的字符串,即历史字符串。
Trie的Java代码:
class Node<Value>{
String key;
Value value;
Node<Value>[] next = (Node<Value>[])new Node[256];
Node(String key, Value value){
this.key = key;
this.value = value;
}
}
class Trie<Value>{
Node<Value> root;
Trie(){
root = new Node<Value>(null, null);
}
//递归 add()
public void add(String key, Value value){
add(key, value, root, 0);
}
private Node add(String key, Value value, Node<Value> cur, int pos){
if(cur == null){
cur = new Node(key.substring(0, pos), null);
}
if(pos == key.length()){
cur.value = value;
return cur;
}
char c = key.charAt(pos);
cur.next[c] = add(key, value, cur.next[c], pos+1);
return cur;
}
//递归 get()
public Value get(String key){
return get(key, root, 0);
}
private Value get(String key, Node<Value> cur, int pos){
if(cur == null) return null;
if(pos == key.length()) return cur.value;
char c = key.charAt(pos);
return get(key, cur.next[c], pos+1);
}
/* //非递归 add()
public void add(String key, Value value){
Node<Value> cur = root;
int i = 0;
while(i < key.length()){
char c = key.charAt(i);
if(cur.next[c] == null){
cur.next[c] = new Node<Value>(key.substring(0, i+1), null);
}
cur = cur.next[c];
i++;
}
cur.value = value;
}
//非递归 get()
public Value get(String key){
int i = 0;
Node<Value> cur = root;
while(i < key.length()){
char c = key.charAt(i);
if(cur.next[c] == null) return null;
cur = cur.next[c];
i++;
}
return cur.value;
} */
public boolean contains(String key){
return get(key) != null;
}
public boolean containPart(String str){
int i = 0;
Node<Value> cur = root;
while(i < str.length()){
char c = str.charAt(i);
if(cur.next[c] == null) return false;
cur = cur.next[c];
i++;
}
return true;
}
}
面试题目代码:
class Node<Value>{
String key;
Value value;
Node<Value>[] next = (Node<Value>[])new Node[256];
Node(String key, Value value){
this.key = key;
this.value = value;
}
}
class Trie<Value>{
//面试题--根据现有字符串求出TRIE已经记录在内的字符串--的粗略方法
public void getRecord(LinkedList<String> res, String key){
if(!containPart(key)) return;
for(int i=0; i<256; i++){
char c = (char)i;
String tmp = key + "" + c;
if(contains(tmp)) res.add(tmp);
getRecord(res, tmp);
}
}
}
总结:
TRIE的具体介绍,以及衍生的SUFFIX数据结构,请参考大牛July的博客。
这里贻笑大方了。