前缀树

前缀树的结构

Trie树,又叫字典树、前缀树(Prefix Tree)、单词查找树或键树,是一种多叉树结构。如下图:

 

 
上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。

Trie树的基本性质: 

  1. 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。 
  2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。 
  3. 每个节点的所有子节点包含的字符互不相同。 
  4. 从第一字符开始有连续重复的字符只占用一个节点,比如上面的to,和ten,中重复的单词t只占用了一个节点。

前缀树的应用

  1. 前缀匹配 
  2. 字符串检索 
  3. 词频统计 
  4. 字符串排序

 

前缀匹配

前缀单词:in,就是 inn 的前缀单词。如果有十几万条单词,并且每个单词的长度都是5-10以内,这样必定存在大量重复的

字符,因此利用前缀树来求解不仅速度快而且空间复杂度也比较好。 

 

代码实现



public class TrieTools {
	private TrieNode root = new TrieNode();
	/**
	 * 字典树的加入过程
	 */
	public void add(String word) {
		if (word == null)
			return;
		char[] chars = word.toCharArray();
		TrieNode node = root;
		for (char c : chars) {
			// 当前节点的子节点不存在这个字符,子节点添加该字符
			if (!node.children.containsKey(c)) {
				node.children.put(c, new TrieNode());
			}
			// 当前节点的子节点存在这个字符,下一个元素位置在子节点的子节点
			node = node.children.get(c);
			// 字符路过这个结点的次数+1
			node.path++;
		}
		// 以当前结点为结束的字符+1
		node.end++;
	}

	/**
	 * 字典树查询目标单词出现的次数
	 */
	public int get(String word) {
		//排除null情况
		if (word == null)return 0;
			
		 
		char[] chars = word.toCharArray();
		TrieNode node = root;
		//查找单词的最后一个节点,该节点记录了这个单词出现的次数
		for (char c : chars) {
			//如果首字符串不在节点中,返回0
			if (!node.children.containsKey(c))return 0;
			
			node = node.children.get(c);
		}
		return node.end;
	}

	/**
	 * 字典树查询以目标前缀的单词有多少个
	 */
	public int getPre(String word) {
		//排除null情况
		if (word == null)return 0;
			
		char[] chars = word.toCharArray();
		TrieNode node = root;
		//查找单词的最后一个节点,该节点记录了这个字符出现的次数,也就是目标前缀的单词的数目
		for (char c : chars) {
			//如果首字符串不在节点中,返回0
			if (!node.children.containsKey(c))return 0;
			node = node.children.get(c);
		}
		return node.path;
	}
	

	public static void main(String[] args) {
		TrieTools trie = new TrieTools();
		trie.add("a");
		trie.add("ab");
		trie.add("ac");
		trie.add("abc");
		trie.add("acb");
		trie.add("abcc");
		trie.add("aab");
		trie.add("abx");
		System.out.println("单词出现的次数: "+trie.get("abc"));
		System.out.println("目标前缀的单词数: "+trie.getPre("ab"));
	}

}







/**
 * 前缀树结构
 */
public class TrieNode {
	/**
	 * path表示字符路过这个结点的次数(即表示存在以当前结点为前缀的字符有多少个);
	 */
    public int path;
    /**
     * end记录以当前结点为结束的字符有多少个。
     */
    public int end;
    /**
     * 子节点
     */
    HashMap<Character, TrieNode> children=new HashMap<Character, TrieNode>();

 
}

测试结果:

单词出现的次数: 1
目标前缀的单词数: 4
 

 

 

过程步骤:

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值