Trie树

Trie树

别称:字典树

树形结构,专门处理字符串匹配的数据结构,解决在一组字符串集合中快速查找某个字符串的问题。

样例: 搜索引擎的提示功能,当搜索东西时,并不用把所有内容都输入进去,一定程度上节省了搜索时间。

什么是Trie树

本质: Trie树的本质,利用字符串之间的公共前缀,将重复的前缀合并在一起。

Trie树的实现

需要实现的功能有两个:

  • 将字符串插入到Trie树
  • 在Trie树查询一个字符串

Trie树的节点

Trie树是一个多叉树,二叉树中一个节点左右节点通过两个指针来存储,在多叉树种,如何存储一个节点的所有子节点指针?

解决: 借助散列表的思想,我们通过下标与字符映射的数组,来存储子节点的指针。

class TrieNode:
	def __init__(self, data:str):
		self._data = data	# 存储数据
		self._children = [None] * 26	# 存储指针,用来存储a~z这26个字母
		self._is_ending = False	# 结尾的标志

将az的下标为025,下标为0存储的是a,下标为25存储的是z,当子节点不存在就是 None

#!/usr/bin/env python

class TrieNode:
	def __init__(self, data:str):
		self._data = data
		self._children = [None] * 26
		self._is_ending = False

class Trie:
	def __init__(self):
		self._root = TrieNode("/")

	def insert(self, text):
		node = self._root
		for index, char in map(lambda x:(ord(x) - ord('a'), x), text):
			if not node._children[index]:
				node._children[index] = TrieNode(char)
			node = node._children[index]
		node._is_ending = True

	def find(self. pattern):
		node = self._root
		for index in map(lambda x:ord((x) - ord('a')), pattern)
			if not node._children[index]: return False
			node = node._children[index]
		return node._is_ending

分析Trie树

时间复杂度

构建 Trie树 的过程,需要扫描所有字符串,时间复杂度是 O(n) (n表示所有字符串长度和)。

查询字符串长度时k,我们只需要对比大约k个节点,就能完成查询操作,时间复杂度是 O(k)

内存的消耗

Trie树是非常耗内存的,用的是一种空间换时间的思路。

问题: 因为每一个节点都要维护一个足够大的数组,当相同的前缀字符串很少时,Trie不但不节省内存,还会浪费更多内存。

内存问题的解决: 牺牲查询效率将节点中的数组换成其他数据结构,存储节点的子节点指针。利用有序数组(降低空间消耗,支持更多字符),数组中的指针按照所指向的子节点中的字符的大小顺序排序,查询的时候,我们可以通过二分查找,快速查找到某个字符应该匹配的子节点的指针,但是在插入一个字符串时,为了维护数组中数据的有序性,就会插入慢一点。

Trie树的变体

缩点优化: 针对只有一个子节点的节点,而且该节点不是一个字符串的结束节点,就可以将此节点与子节点合并,这样就能节省空间。

Tire树的比较

字符串匹配问题,就是数据查找问题,实际上支持动态数据高效操作的数据结构(散列表、红黑树、跳表等),这些数据也能实现字符串查找功能。

Trie树的适用场景

  1. 字符串包含字符集不能太大,那么存储空间会浪费很多,虽然可以优化,但是牺牲查询、插入效率的代价。
  2. 要求字符串的前缀重合比较多,不然空间消耗会变大很多。
  3. 要用Trie树来解决问题,需要从零开始实现一个Trie树。
  4. 通过指针串连接的数据块是不连续的,而Trie树用到了指针,对缓存不是很友好,性能会打折扣。

针对一组字符中查找字符串问题,工程中更倾向使用散列表或红黑树,因为不需要自己实现,直接去使用库就行了。

优点: Trie树不适合精确匹配查找,精确匹配适合红黑树和散列表,Tire树适合查找前缀匹配的字符串。

缺点: 不适用与动态集合数据的查找,这种适用于红黑树和散列表。

使用场景

  1. 自动输入补全
  2. IDE代码编辑器自动补全
  3. 浏览器网址自动补全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值