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

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();
    }
}

 

 

    原文作者:Trie树
    原文地址: https://blog.csdn.net/leichenlei/article/details/75529960
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞