树形结构----Trie树

本文详细介绍了Trie树,包括其定义、实现原理以及在单词查找、计数、添加和判断中的应用。重点展示了字典树的数据结构和如何利用AVL树映射实现高效字符串搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Trie树的定义:Trie树也叫字典树,单词查找树,是一种多叉树专门处理字符串 查询每个条目的时间复杂度,和树中一共多少条目无关,其时间复杂度为O(w),w为所查询单词的长度,大多数单词的长度小于10(优势)。

2. Trie树的实现:

//定义Trie树又称字典树 字典树是专门对字符串或字符进行操作的一种树 因此我们在定义是不需要再定义泛型
/*
* 字典树的存储特点:根节点不存放数据 且字典树属一种多叉树 每个节点存放的是字符串或字符的一个字母 
* 并且对字符串进行的是有序的存储 树中不会存放重复的首字母
* 我们这里的字典树的节点是一个映射 键 指的是字符串或字符的字母
* 值 指的是当前字母的节点的孩子节点(孩子节点为当前字母再字符串或字符中的下一个字母)
* 相当于是映射中嵌套映射
*/
public class Trie {
	
	//定义节点 节点包含三部分
	private class Node{
		public boolean isWord; //表示当前字母的组成是否是一个完整的单词
		public int count; //表示当前单词出现的次数
		public AVLTreeMap<Character, Node> children; //表示当前字母的映射
		
		public Node() {
			this(false);
		}
		
		public Node(boolean isWord) {
			this.isWord = isWord;
			count = 0;
			children = new AVLTreeMap<Character, Node>();
		}
	}
	
	private Node root; //表示trie树的根节点
	
	private int size; //表示trie中完整单词的个数 不包括重复单词
	
	public Trie() {
		root = new Node();
		size = 0;
	}
	
	//获取trie中完整单词的个数 不包括重复单词
	public int size() {
		return size;
	}
	
	//获取指定单词在trie树中出现的次数
	/*
	 * 首先定义一个游标 从trie树的根节点开始
	 * 遍历单词的每一个字母 判断当前节点的映射中是否包含该字母
	 * 如果不包含则返回0 表示trie树中没有指定单词
	 * 反之更新游标 使游标指向当前字母的值
	 * 值 指的是当前字母的节点的孩子节点(孩子节点为当前字母再字符串或字符中的下一个字母)
	 * 遍历字符串或字符结束后 判断当前是否是一个完整的单词 如果是返回当前节点的count
	 * 如果不是(比如时一个前缀等) 返回0
	 */
	public int count(String word) {
		Node cur = root;
		for(int i = 0; i < word.length(); i++) {
			char c = word.charAt(i);
			if(!cur.children.contains(c)) {
				return 0;
			}
			cur = cur.children.get(c);
		}
		if(cur.isWord) {
			return cur.count;
		}else {
			return 0;
		}
	}
	
	//向trie中添加指定单词
	/*
	 * 首先定义一个游标 从trie树的根节点开始
	 * 遍历单词的每一个字母 判断当前节点的映射中是否包含该字母
	 * 如果不包含就将该字母添加到映射中(该字母就为映射中的键 而值表示当前字母的节点的孩子节点)
	 * 更新游标 使游标指向当前字母的值
	 * 值 指的是当前字母的节点的孩子节点(孩子节点为当前字母再字符串或字符中的下一个字母)
	 * 遍历字符串或字符结束后 判断当前字母的组成是否是一个完整的单词即isWord是否为false
	 * 如果是false 就将当前节点的isWord置为true trie中完整单词的个数(不包括重复单词)加一
	 * 反之则表示trie树中已经有该单词 则该单词数量加一
	 */
	public void put(String word) {
		Node cur = root;
		for(int i = 0; i < word.length(); i++) {
			char c = word.charAt(i);
			if(!cur.children.contains(c)) {
				cur.children.put(c, new Node());
			}
			cur = cur.children.get(c);
		}
		if(!cur.isWord) {
			cur.isWord = true;
			size++;
			cur.count = 1;
		}else {
			cur.count++;
		}
	}
	
	//判断trie树中是否包含指定单词
	/*
	 * 首先定义一个游标 从trie树的根节点开始
	 * 遍历单词的每一个字母 判断当前节点的映射中是否包含该字母
	 * 如果不包含则返回false 表示没有指定单词
	 * 反之更新游标 使游标指向当前字母的值
	 * 值 指的是当前字母的节点的孩子节点(孩子节点为当前字母再字符串或字符中的下一个字母)
	 * 遍历字符串或字符结束后 返回节点的isWord
	 */
	public boolean contains(String word) {
		Node cur = root;
		for(int i = 0; i < word.length(); i++) {
			char c = word.charAt(i);
			if(!cur.children.contains(c)) {
				return false;
			}
			cur = cur.children.get(c);
		}
		return cur.isWord;
	}
	
	//判断trie树中是否包含指定前缀
	/*
	 * 首先定义一个游标 从trie树的根节点开始
	 * 遍历单词的每一个字母 判断当前节点的映射中是否包含该字母
	 * 如果不包含则返回false 表示没有指定前缀
	 * 反之更新游标 使游标指向当前字母的值
	 * 值 指的是当前字母的节点的孩子节点(孩子节点为当前字母再字符串或字符中的下一个字母)
	 * 遍历字符串或字符结束后 返回true 表示trie树中包含指定前缀
	 */
	public boolean isPrefix(String prefix) {
		Node cur = root;
		for(int i = 0; i < prefix.length(); i++) {
			char c = prefix.charAt(i);
			if(!cur.children.contains(c)) {
				return false;
			}
			cur = cur.children.get(c);
		}
		return true;
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值