字典树实例--java实现

         当我们在百度上搜索的时候,在输入框里输入字符,会启发式得通知我们可能输入什么。当在翻译软件里面输入单词的时候,也会启发得显示出以我们的输入为前缀的单词。这其实用的就是字典树,或者他的变种。

        字典树用于保存字符串,节省空间。他把多个字符串相同的前缀只保存依次,并且提高查询效率。多用于查询给定前缀的所有字符,或者查询给定前缀的所有字符数量。

       字典树的节点代码:

       

/**
	 * TrieNode: 字典树节点
	 * 
	 * @author xuejupo [email protected] 
	 * create in 2015-11-27 下午5:41:07
	 * 
	 */
	class TrieNode {
		private int num;// 该节点有多少孩子
		private TrieNode[] son = null; // 所有的孩子节点
		private boolean isEnd; // 是否结束节点
		private char val; // 节点的值

		TrieNode() {
			num = 0;
			son = new TrieNode[SIZE];
			isEnd = false;
		}
	}

     插入节点:

/**
	 * insert: 字典树的插入
	 * 
	 * @param str
	 *            void 返回类型
	 */
	public void insert(String str) {
		if (str == null || str.length() == 0) {
			return;
		}
		TrieNode node = root;
		char[] letters = str.toCharArray();
		for (int i = 0, len = str.length(); i < len; i++) {
			int pos = letters[i] - 'a';
			if (node.son[pos] == null) {
				node.son[pos] = new TrieNode();
				node.son[pos].val = letters[i];
			} else {
				node.son[pos].num++;
			}
			node = node.son[pos];
		}
		node.isEnd = true;
	}

 统计以pre为前缀的单词个数

/**
	 * countPre: 计算以pre为前缀的单词的个数
	 * 
	 * @param pre
	 * @return int 返回类型
	 */
	public int countPre(String pre) {
		if (pre == null || pre.length() == 0) {
			return -1;
		}
		TrieNode node = root;
		char[] letters = pre.toCharArray();
		for (int i = 0, len = pre.length(); i < len; i++) {
			int pos = letters[i] - 'a';
			if (node.son[pos] == null) {
				return 0;
			} else {
				node = node.son[pos];
			}
		}
		return node.num;
	}

     获取以pre为前缀的所有单词

/**  
	* getPre: 获取pre前缀的树中所有的String的list
	* @param pre
	* @return 
	* List<String>  返回类型   
	*/
	public List<String> getPre(String pre) {
		if (pre == null || pre.length() == 0) {
			return Collections.emptyList();
		}
		List<String> result = new ArrayList<String>();
		TrieNode node = root;
		char[] letters = pre.toCharArray();
		for (int i = 0, len = pre.length(); i < len; i++) {
			int pos = letters[i] - 'a';
			if (node.son[pos] == null) {
				return Collections.emptyList();
			} else {
				node = node.son[pos];
			}
		}
		StringBuilder sb = new StringBuilder(pre);
		getPre(node,sb,result);
		return result;
	}
/**  
	* getPre: 将树里面以pre为前缀的所有String放入list
	* @param node
	* @param sb
	* @param l 
	* void  返回类型   
	*/
	public void getPre(TrieNode node,StringBuilder sb,List<String> l){  
    	if(node != null && node.isEnd){
    	 l.add(sb.toString());
    	}
        if(node!=null){  
            for(TrieNode child: node.son){  
            	if(child != null){
	            	sb.append(child.val);
	            	getPre(child,sb,l);  
            	}
            }  
        }  
    }

 查询单词是否在字典树中:

/**
	 * isExist: 查询str是否在字典树中
	 * 
	 * @param str
	 * @return boolean 返回类型
	 */
	public boolean isExist(String str) {
		if (str == null || str.length() == 0) {
			return false;
		}
		TrieNode node = root;
		char[] letters = str.toCharArray();
		for (int i = 0, len = str.length(); i < len; i++) {
			int pos = letters[i] - 'a';
			if (node.son[pos] != null) {
				node = node.son[pos];
			} else {
				return false;
			}
		}
		return node.isEnd;
	}

 测试函数:

public static void main(String[] s){
		Trie t = new Trie();
		t.insert("abc");
		t.insert("abcasd");
		t.insert("abca");
		t.insert("a");
		t.insert("asda");
		t.insert("ba");
		System.out.println("测试des是否存在字典树中:"+t.isExist("des"));
		System.out.println("插入des");
		t.insert("des");
		System.out.println("测试des是否存在字典树中:"+t.isExist("des"));
		System.out.println("输出以ab为前缀的所有单词:");
		for(String p:t.getPre("ab")){
			System.out.print(p+"\t");
		}
	}

 测试结果:

测试des是否存在字典树中:false
插入des
测试des是否存在字典树中:true
输出以ab为前缀的所有单词:
abc	abca	abcasd	

猜你喜欢

转载自709002341.iteye.com/blog/2260944
今日推荐