单词查找树符号表数据结构实现
本文参考《算法(第4版)》
单词查找树符号表数据结构实现
1.实现代码
-
单词查找树是字符串符号表的一种数据结构。
单词查找树的每个节点含有一个值和一个大小为R的字符串数组,该数组存放R个链接,字符串作为该节点的键,即作为数组的索引。所以也称作R向单词查找树。每条链接指向下一个节点。如果一个字符串的尾字符对应的树中的节点的值不为空,则说明查找命中,即该树存在该字符串;如果一个字符串的尾字符对应的树中的节点的值为空,或者对应一个空链接(节点不存在),则说明查找未命中,即该树不存在该字符串。
-
单词查找树的主要操作有:
查找所有的键,查找,插入,删除一个键,查找给定字符串在树中的最长键前缀,查找匹配模式字符串的所有字符串,查找以某个字符前缀的所有字符串等。
package algorithms.stringrank;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
public class TrieST<T>{
private static int R = 256;
private Node root;
public static class Node{
private Object val;
private Node[] next = new Node[R];
}
public int size(){
return size(root);
}
private int size(Node x){
if(x == null) return 0;
int count = 0;
if(x.val != null) count++;
for(char i = 0; i < R; i++)
count += size(x.next[i]); //每一层递归都有一个方法内局部变量count
return count;
}
public T get(String key){
Node x = get(root, key, 0);
if(x.val == null) return null;
return (T)x.val;
}
private Node get(Node x, String key, int d){
if(x == null) return null;
if(d == key.length()) return x; //索引d控制是否达到字符串末尾
int c = key.charAt(d);
return get(x.next[c], key, d+1);
}
public void put(String key, T val){
root = put(root, key, val, 0);
}
private Node put(Node x, String key, T val, int d){
if(x == null) x = new Node();
if(d == key.length()){
x.val = val;
return x;
}
int c = key.charAt(d);
x.next[c] = put(x.next[c], key, val, d+1);
return x;
}
//单词查找树中所有的字符串
public Iterable<String> keys(){
return keyWithPrefix("");
}
public Iterable<String> keyWithPrefix(String pre){
Queue<String> q = new LinkedList<String>();
collect(get(root, pre, 0), pre, q);
return q;
}
private void collect(Node x, String pre, Queue<String> q){
if(x == null) return;
if(x.val != null) q.add(pre);
for(char c = 0; c < R; c++)
collect(x.next[c], pre+c, q);
}
//通配符匹配
public Iterable<String> keysThatMatch(String pat){
Queue<String> q = new LinkedList<String>();
collect(root, "", pat, q);
return q;
}
private void collect(Node x, String pre, String pat, Queue<String> q){
int d = pre.length();
if(x == null) return;
if(d == pat.length() && x.val != null) q.add(pre);
if(d == pat.length()) return;
char next = pat.charAt(d);
for(char c = 0; c < R; c++)
if(next == '.' || next == c)
collect(x.next[c], pre+c, pat, q);
}
//查找最长键前缀
public String longestPrefixOf(String s){
int length = search(root, s, 0, 0);
return s.substring(0, length);
}
private int search(Node x, String s, int d, int length){
if(x == null) return length;
if(x.val != null) length = d; //当前最大值
if(d == s.length()) return length;
int c = s.charAt(d);
return search(x.next[c], s, d+1, length);
}
//删除操作
public void delete(String key){
root = delete(root, key, 0);
}
private Node delete(Node x, String key, int d){
if(x == null) return null;
if(d == key.length()) x.val = null;
else{
char c = key.charAt(d);
x.next[c] = delete(x.next[c], key, d+1);
}
if(x.val != null) return x; //当前节点有值不做处理
for(char c = 0; c < R; c++)
if(x.next[c] != null) return x; //判断当前节点是否有非空链接
return null;
}
public static void main(String[] args) {
String[] a = new String[]{"the","air","by","them","she","shell",
"shells","airby","shert","theme","airport","bybike"};
Integer[] b = new Integer[]{4,5,6,7,8,9,10,1,2,3,11,12};
TrieST<Integer> triest = new TrieST<Integer>();
for(int i = 0; i < a.length; i++)
triest.put(a[i], b[i]);
System.out.println("the triest length: " + triest.size());
System.out.println("airport = " + triest.get("airport"));
System.out.println("打印所有的键:");
for(String s : triest.keys())
System.out.println(s);
System.out.println("以a开头的键:");
for(String s : triest.keyWithPrefix("a"))
System.out.println(s);
System.out.print("与'a..'匹配的键:");
for(String s : triest.keysThatMatch("a.."))
System.out.println(s);
System.out.print("与'them.'匹配的键:");
for(String s : triest.keysThatMatch("them."))
System.out.println(s);
System.out.print("airport的最长键:");
for(String s : triest.keysThatMatch("airport")){
System.out.println(s);
}
System.out.print("bybikes的最长键:");
for(String s : triest.keysThatMatch("bybike")){
System.out.println(s);
}
System.out.println("删除键'airby'后:");
triest.delete("airby");
for(String s : triest.keys())
System.out.println(s);
System.out.println("删除键'theme'后:");
triest.delete("theme");
for(String s : triest.keys())
System.out.println(s);
}
}
输出:
the triest length: 12
airport = 11
打印所有的键:
air
airby
airport
by
bybike
she
shell
shells
shert
the
them
theme
以a开头的键:
air
airby
airport
与'a..'匹配的键:air
与'them.'匹配的键:theme
airport的最长键:airport
bybikes的最长键:bybike
删除键'airby'后:
air
airport
by
bybike
she
shell
shells
shert
the
them
theme
删除键'theme'后:
air
airport
by
bybike
she
shell
shells
shert
the
them