单词查找树TrieSTtest.java

来源:互联网 发布:怎样提高淘宝买家信誉 编辑:程序博客网 时间:2024/06/08 15:16
package string;import java.util.LinkedList;import java.util.Queue;public class 单词查找树TrieSTtest {    public static void main (String[] args){        TrieST<Integer> tri = new TrieST<Integer>();         tri.put("zhangsan", 23);        tri.put("zhage", 24);        tri.put("lisi", 25);        /*System.out.println(tri.get("zhage"));        tri.delete("zhage");        System.out.println(tri.get("zhage"));        Iterable<String> i = tri.keys();//可以看一下Iterable<String>的文档         //Implementing this interface allows an object to be the target of the "foreach" statement.        for(String s:i)            System.out.println(s);        i = tri.keysWithPrefix("li");        for(String s:i)            System.out.println(s);        */        Iterable<String> i = tri.keysThatMath(".i..");        for(String s:i)            System.out.println(s);        System.out.println(tri.longestPrefixOf("zhangsandfdf"));    }}class TrieST<Value>{    private static int R = 256;//基数    private Node root;    private static class Node{        private Object val;//对于一个字符串,当然会有对应的value,例如 : 张三  21        private Node[] next = new Node[R];//不止26个字母    }    //因为Java不支持泛型数组,所以此处类型必须为Object,可以在get()中将值的类型转换成为Value    /*否则可以这样     * private static class Node<Value>{     * private Value val;     * private Node<Value>[] next = new Node<Value>[R];//不止26个字母     * }     */    public void put(String key,Value val){        root = put(root,key,val,0);    }    private Node put(Node x,String key,Value val,int d){        // 如果key存在于以x为根节点的子单词查找树中,就更新与他相关联的值        if(x==null)             x = new Node();        if(d == key.length()){//每一个结点有一个value 和 一个256大小的next[下标是第d个单词对应的ACSII值]数组,其值为下一个结点(对应第d个单词)            x.val = val;            return x;        }        char c = key.charAt(d);        x.next[c] = put(x.next[c],key,val,d+1);        return x;    }    public Value get(String key){        Node x = get(root,key,0);//返回的是单词所在的结点        if(x == null)             return null;        return (Value)x.val;    }    private Node get(Node x,String key,int d){        if(x == null)                  //这个d是标记匹配到key的第几个字符            return null;        if(d == key.length())            return x;        char c = key.charAt(d);//找到第d个字符对应的子单词查找树        return get(x.next[c],key,d+1);    }    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)//找到后如果当前节点有值,x还有用            return x;        for(char c=0;c<R;c++)//如果当前节点有其他的分支,x还有用            if(x.next[c] != null)                return x;        return null;//x没有用了,返回null就可以了    }    //收集一棵单词查找树中的所有键的轨迹    public Iterable<String> keys(){        return keysWithPrefix("");//结果是大的    }    public Iterable<String> keysWithPrefix(String pre){        Queue<String> q = new LinkedList<String>();        collect(get(root,pre,0),pre,q);              //从get(root,pre,0)为根结点进行遍历        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);                   //递归遍历,  拼接字符串    }    //单词查找树中的通配符匹配(通配符是进行填充的)        //pat就是要被匹配的    public Iterable<String> keysThatMath(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();   //因为这里需要pre这个参数,那么干脆把d这个参数去掉吧        if(x == null)            return;        if(d == pat.length()&& x.val != null)//只要匹配的长度跟用通配符匹配的pat长度相等,说明匹配完成            q.add(pre);        if(d == pat.length())            return;        char next = pat.charAt(d);//如果pat中已经匹配了d长度的字符串,那么下一个要匹配的是pat中第d个字符        for(char c=0;c<R;c++)            if(next == '.' || next == c)//当前的pat中的第d个字符是 . 说明不管c是什么都行;当前的pat中的第d个字符正好是c,可以继续                collect(x.next[c],pre+c,pat,q);    }    //对给定字符串的最长前缀进行匹配    public String longestPrefixOf(String pat){//结果返回的是小的字符串        int length = search(root,pat,0,0);        return pat.substring(0,length);    }    private int search(Node x,String pat,int d,int length){        if(x == null)            return length;        if(x.val != null)            length = d;//只有val不是null的时候才会更新length        if(d == pat.length())//如果pat全部找完了就不用找了            return length;        char c = pat.charAt(d);        return search(x.next[c],pat,d+1,length);    }}
原创粉丝点击