Trie字典树、数字查找、键树

来源:互联网 发布:数控外圆磨床编程案例 编辑:程序博客网 时间:2024/06/05 16:33

1,需要先将要被查找的文字通过structure方法按照拼音构建成一棵树,每个匹配节点上装有查找目标对象。

 

2,完成的功能:用户在输入框里输入拼音或者汉字,输入内容转化成拼音,然后按照拼音遍历树,找到结果。

 

3,用到了开元包pinyin4j

 

4,没有考虑多音字。可以按需要对多音字做多路径存储。子节点可以优化成map结构,优化遍历速度。

 

package com.test.common.utils;import java.io.Serializable;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;/** * Trie字典树类,节点用内部类Node表示,提供构建树、插入节点、搜索、等方法。 * 需要优化的地方:1,多音字,2子节点的存储结构和查找 * @author yfchenlei * @date 2012-9-12 */public class Trie<T> implements Serializable{private static final long serialVersionUID = 5694541776693908755L;/** * 根节点 */private Node<T> root;/** * 最大搜索结果个数 */private int maxResult = 10;/** *  默认构造方法 */public Trie(){}/** * 带参构造方法 * @param maxResult 最大搜索结果个数 */public Trie(int maxResult){this.maxResult = maxResult;}/** * 根据传入数据集合构建一颗字典树 * @param words 数据集合 */public void structure(Map<String, T> items){root = new Node<T>('0');if(items == null){return;}Iterator<String> it = items.keySet().iterator();while(it.hasNext()){String key = it.next();T value= items.get(key);if(value != null){insert(key, value);}}}/** * 向字典树插入一个数据,word。 * @author yfchenlei * @date 2012-9-12 * @param word 要插入到字典树的数据 */public void insert(String word,T item){String pinyin = PinYin.cn2Pinyin(word);if(root == null){root = new Node<T>('0');}Node<T> curNode = root;int wordLength = pinyin.length();for(int i = 0; i< wordLength; i++){char value = pinyin.charAt(i);Node<T> nextNode = curNode.getChild(value);if(nextNode == null){nextNode = new Node<T>(value);curNode.addChild(nextNode);}curNode = nextNode;}curNode.addItem(item);}/** * 根据输入的word的拼音,查找符合这个拼音前缀的所有集合,但不超过最大结果个数。 * @author yfchenlei * @date 2012-9-12 * @param word 根据这个数据进行查找 * @return 符合条件的集合 */public List<T> find(String word){List<T> result = new ArrayList<T>(maxResult);if(root == null || word == null){return result;}String pinyin = PinYin.cn2Pinyin(word);Node<T> curNode = root;for(int i = 0; i < pinyin.length(); i++){Node<T> child = curNode.getChild(pinyin.charAt(i));if(child != null){curNode = child;}else{return result;}}result = traverse(curNode, result);return result;}/** * 遍历字典树的递归方法,每次递归,将结果积累到result参数。 * @author yfchenlei * @date 2012-9-12 * @param node 当前节点 * @param result 结果集合 * @return 返回最后的集合 */private List<T> traverse(Node<T> node, List<T> result){if(node == null || result.size() == maxResult){return result;}List<T> items = node.getItems();if(items != null){if(result.size() + items.size() > maxResult){for(int i = 0; i < maxResult - result.size(); i++){result.add(items.get(i));}}else{result.addAll(node.getItems());}}Node<T>[] children = node.getChildren();if(children != null){for(int i = 0; i < children.length; i++){if(result.size() == maxResult){break;}traverse(children[i], result);}}return result;}/** * trie的子类,表示树节点 * @author yfchenlei * @date 2012-9-12 */@SuppressWarnings("hiding")class Node<T> implements Serializable{private static final long serialVersionUID = -7145041421696945423L;/** * 节点的路径值 */private char value;/** * 子节点集合 */private Node<T>[] children;/** * 节点中的值集合,因为拼音可能重复,所以是集合。 */private List<T> items;public Node(char value){this.value = value;}public void addItem(T item){if(items == null){items = new ArrayList<T>(1);}items.add(item);}public void addChild(Node<T> node){if(children == null){this.children = new Node[26];}children[node.getValue() - 'a'] = node;}public Node<T> getChild(char value){int pos = value - 'a';if(children == null){return null;}return children[pos];}public char getValue() {return value;}public Node<T>[] getChildren() {return children;}public List<T> getItems() {return items;}}}

 用到的转化拼音工具:

 

package com.test.common.utils;import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;/** * 汉字转拼音支持工具 * @author yfchenlei * @date 2012-9-13 */public class PinYin {private static HanyuPinyinOutputFormat defaultFormat;static{defaultFormat = new HanyuPinyinOutputFormat();         defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);         defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);}public static String cn2Pinyin(String cn){StringBuffer result = new StringBuffer();char[] chars = cn.toCharArray();try {        for(int i = 0; i < chars.length; i++){        if(chars[i] > 128){        String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(chars[i], defaultFormat);        result.append(pinyin[0]);        }else{        char letter = Character.toLowerCase(chars[i]);        if(letter >= 98 && letter <= 122)        result.append(chars[i]);        }        }} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();return null;}        return result.toString();}}

 

 

原创粉丝点击