package com.txq.ternaryTree;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义三叉树
* @author TongXueQiang
* @date 2016/03/03
* @since JDK 1.7
*/
public class TernaryTree {
// 根节点
private static Node root;
// 存储前缀匹配结果的集合
private Set<String> result = new HashSet<String>();
/**
* 向树中插入字符
*
* @param node
* @param word
* @return
*/
public void insert(String word) {
root = insert(root, word, 0);
}
/**
* 插入字符具体实现
*
* @param node
* @param word
* @param index
* @return
*/
private Node insert(Node node, String word, int index) {
if (word == null || word.equals("")) {
return null;
}
char[] charArray = word.toCharArray();
// 如果节点为空,创建新的节点
if (node == null) {
node = new Node(charArray[index], false);
}
// 如果当前字符小于当前节点存储的字符,插入左节点的位置
if (charArray[index] < node.storedChar) {
node.leftNode = insert(node.leftNode, word, index);
}
// 如果当前字符大于当前节点存储的字符,插入右节点的位置
else if (charArray[index] > node.storedChar) {
node.rightNode = insert(node.rightNode, word, index);
} else {// 相等
// 递归终止条件
if (index == charArray.length - 1) {
node.isCompleted = true;
} else {
node.centerNode = insert(node.centerNode, word, ++index);
}
}
return node;
}
/**
* 查找以指定前缀开头的所有字符串
*
* @param prefix
* @return
*/
public Set<String> searchPrefix(String prefix) {
// 首先查找前缀的下一个centerNode
Node node = findNode(prefix);
return searchPrefix(node, prefix);
}
/**
* 查找以指定前缀开头的所有字符串的具体实现
*
* @param node
* @param prefix
* @return
*/
private Set<String> searchPrefix(Node node, String prefix) {
if (node != null) {//递归终止条件
//如果是成词,加入到结果集中
if (node.isCompleted) {
result.add(prefix + node.storedChar);
}
searchPrefix(node.leftNode,prefix);//向左查找
searchPrefix(node.centerNode,prefix + node.storedChar);//向中间查找
searchPrefix(node.rightNode,prefix);//向右查找
}
//如果前缀是成词
if (isWord(prefix))
result.add(prefix);
return result;
}
/**
* 判断前缀是否为成词
* @param prefix
*/
private boolean isWord(String prefix) {
return isWord(root,prefix,0);
}
private boolean isWord(Node node, String prefix, int index) {
if (node == null) {
return false;
}
char[] charArray = prefix.toCharArray();
// 如果当前字符小于当前节点存储的字符,查找左节点
if (charArray[index] < node.storedChar) {
return isWord(node.leftNode, prefix, index);
}
// 如果当前字符大于当前节点存储的字符,查找右节点
else if (charArray[index] > node.storedChar) {
return isWord(node.rightNode, prefix, index);
} else {// 相等
// 递归终止条件
if (index == charArray.length - 1) {
if (node.isCompleted ) {
return true;
}
return false;
}
else {
return isWord(node.centerNode, prefix, ++index);
}
}
}
/**
* 查找前缀的下一个centerNode,作为searchPrefix的开始节点
*
* @param prefix
* @return
*/
private Node findNode(String prefix) {
return findNode(root, prefix, 0);
}
private Node findNode(Node node, String prefix, int index) {
if (prefix == null || prefix.equals("")) {
return null;
}
if (node == null) {
return null;
}
char[] charArray = prefix.toCharArray();
// 如果当前字符小于当前节点存储的字符,查找左节点
if (charArray[index] < node.storedChar) {
return findNode(node.leftNode, prefix, index);
}
// 如果当前字符大于当前节点存储的字符,查找右节点
else if (charArray[index] > node.storedChar) {
return findNode(node.rightNode, prefix, index);
} else {// 相等
// 递归终止条件
if (index == charArray.length - 1) {
return node.centerNode;
}
else {
return findNode(node.centerNode, prefix, ++index);
}
}
}
/**
* 加载主字典
*/
public void loadDict() {
InputStream is = super.getClass().getClassLoader().getResourceAsStream("com/txq/ternaryTree/word.dic");
if (is == null) {
throw new RuntimeException("Main Dictionary not found!!!");
}
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"),512);
String newWord = null;
do {
newWord = br.readLine();
if (newWord != null && !"".equals(newWord.trim())) {
this.insert(newWord);
}
}while(newWord != null);
}catch(Exception e){
e.printStackTrace();
}
finally{
try {
if (is != null) {
is.close();
is = null;
}
} catch(Exception e){
e.printStackTrace();
}
}
}
}
以下是测试类:
package com.txq.ternaryTree;
import java.util.Set;
public class Test {
public static void main(String[] args) {
// String originalWord = "acfbedg";
// String result = QuickSortAndCompromise.sortAndCompromise(originalWord, new StringBuffer());
// System.out.println(result);
TernaryTree t = new TernaryTree();
t.loadDict();
Set<String> result = t.searchPrefix("中华");
System.out.println(result);
}
}