CS61B - Lec 26 - Tries


这两天晚上都没睡好导致脑子木木的,昨天实现个HashMap实现了一晚上,还把resize的条件写成了> loadFactor。。。顺便看了下HashMap的源码,好像还用到了红黑树,相当的复杂,好多东西我都没考虑到。
今天学习的是专门存储key为String, char类型的Map——Trie。Trie是搜索引擎中Autocomplete的核心数据结构。

Tries

我们知道,数组的查找时间是O(1),另外,char都可以用ASCII码来表示。所以,可以用数组建一个char——V的Map,如下图:
在这里插入图片描述
查找速度非常快,然而如何存储一整个单词呢?我们想到可以用多个连续的存储char的节点代表一个单词,这就是Trie。
在这里插入图片描述
trie就是这样一种结构。当存储的值均能被ASCII码表示时,就在一个节点放一个char,并用蓝色标记一个单词的结束,就相当于存储了一个String。

Implementaion and Performance

第一种实现方法。还是以一个节点为基础(可以发现无论是List, BST, HashMap,都先要有节点的思想),节点中存储颜色(isKey),char,以及上面提到的DataIndexedCharMap类型的next,包含子节点的位置。
在这里插入图片描述
具体的结构是这个样子的:
在这里插入图片描述
所以它是一种下图的结构。每个节点都有128个分支,有一些分支包含下一个节点,下标就代表下一个节点中的字母。
在这里插入图片描述
这是就发现节点中根本不用存一个字母,靠next中的数据就足够了。
在这里插入图片描述
查找和插入的复杂度都是O(L)。我们可以从顶端试一遍。所有单词开头都包含在root的128个分支中,+1,到达下一个节点;再找下一个字母,依然+1(注意DataIndexedCharMap结构)…最后就是O(L)的复杂度,L为一个单词的长度。
在这里插入图片描述
可见Trie存储字符的效率极高。HashTable会有resize的问题,虽然平均下来仍然是O(1)复杂度,并且可能有多个数据存储在一个hashCode里,Trie可是实打实的O(L)。

还有一个问题就是内存浪费。数组中有大量的null,并不需要这么长的数组。

Alternate Child Tracking Strategies

在这里插入图片描述
想到了用更高级的数据结构实现char - Node这样一个map,比如BST和HashTable。(其实自己实现HashMap的时候我想过每个Node包含一个HashSet替换一般的链表结构。但是问题就来了:那最开始的HashSet用什么呢?)

这也体现了ADT的设计理念,一个功能可以有很多不同的实现形式,各有利弊。
在这里插入图片描述
运用BST和HashMap会轻微提高复杂度,但并不明显,因为总共也就128个,怎么着都是常数复杂度。节省的内存倒是大量的,综合来看,还是HashTable最优。

Trie String Operations

开头就提到了,Trie这个结构被广泛用于搜索引擎的提示功能。这时就要实现一个perfix matching的功能,就是找到有指定的相同前缀的所有单词。
在这里插入图片描述
一步一步实现这个功能,首先,如何找到所有的key呢?依然是recursion。建一个list x,调用colHelp方法,输入root的各子字符对应的子节点,return x。
colHelp是recursion实现方式:结束条件是碰见一个蓝色节点,也就是一个单词结束的节点,就向x中加入该字符。遍历所有的子节点,调用colHelp方法。
在这里插入图片描述
实现找到相同前缀的单词,就只需要找到前缀所在的节点,然后调用colHelp方法即可。
在这里插入图片描述

Autocomplete

下面就可以实现神秘的autocomplete了!

这里的trie里面是一个Map,每个String都有一个对应的value,表示优先级(搜索的次数)。当我们输入一部分字符时,会自动调用找相同前缀的方法,然后返回value大小前十的String。就这么简单!当然细节很复杂。
在这里插入图片描述
如图,每个String的结尾,蓝色节点的value代表该String的优先级。
在这里插入图片描述
有一个问题是,这种autocomplete是建立在庞大的数据库的基础上,那么这里的trie是个相当庞大的数据集。如果输入的字符很短时,就会有一堆字符串有着相同的前缀,还要遍历每个字符直到底部,才能找到每个字符的value,这是非常没有效率的。
在这里插入图片描述
更有效率的方法是,每个节点都额外存储一个subString value,代表优先级最高的subString的value。然后优先去包含这个value的子节点里寻找。
在这里插入图片描述

发布了20 篇原创文章 · 获赞 0 · 访问量 170

猜你喜欢

转载自blog.csdn.net/fourier_transformer/article/details/105531242