Dictionary 保存字典的好数据结构是什么?
我正在设计一个单词过滤器,可以过滤掉一篇文章中的坏单词(列表中有200个单词)(大约2000个单词)。我有一个问题,我需要保存这个坏单词列表,这样程序就可以用一点时间在文章中找到坏单词 --更多细节Dictionary 保存字典的好数据结构是什么?,dictionary,data-structures,Dictionary,Data Structures,我正在设计一个单词过滤器,可以过滤掉一篇文章中的坏单词(列表中有200个单词)(大约2000个单词)。我有一个问题,我需要保存这个坏单词列表,这样程序就可以用一点时间在文章中找到坏单词 --更多细节 如果坏词列表的大小为2000,则文章数为50000,程序一次将处理大约1000篇文章。我应该选择哪个数据结构来搜索,一个小于O(n^2)的解决方案?我认为最好的结构,你可以使用那里的集合- 我花费log_2(n)时间将元素添加到结构中(一次操作),并对每个查询给出相同的答案。因此,如果您的数据结构中
如果坏词列表的大小为2000,则文章数为50000,程序一次将处理大约1000篇文章。我应该选择哪个数据结构来搜索,一个小于O(n^2)的解决方案?我认为最好的结构,你可以使用那里的
集合
-
我花费
log_2(n)
时间将元素添加到结构中(一次操作),并对每个查询给出相同的答案。因此,如果您的数据结构中有200个元素,那么您的程序只需执行大约8个操作即可检查单词是否存在于set
您可以使用哈希表,因为其插入和搜索的平均复杂度为O(1),而您的数据只有2000个单词。
词典通常是从一个事物(第一语言中的单词)到另一个事物(第二语言中的单词)的映射。这里似乎不需要这个映射,只需要一组单词
大多数语言都提供了一个现成的数据结构集,它具有插入和成员测试方法
Python中的一个小示例,比较列表
和集
:
import random
import string
import time
def create_word(min_len, max_len):
return "".join([random.choice(string.ascii_lowercase) for _ in
range(random.randint(min_len, max_len+1))])
def create_article(length):
return [create_word(3, 10) for _ in range(length)]
wordlist = create_article(50000)
article = " ".join(wordlist)
good_words = []
bad_words_list = [random.choice(wordlist) for _ in range(2000)]
print("using list")
print(time.time())
for word in article.split(" "):
if word in bad_words_list:
continue
good_words.append(word)
print(time.time())
good_words = []
bad_words_set = set(bad_words_list)
print("using set")
print(time.time())
for word in article.split(" "):
if word in bad_words_set:
continue
good_words.append(word)
print(time.time())
这将创建一篇由50000个随机创建的“单词”组成的“文章”,长度在3到10个字母之间,然后选择其中的2000个单词作为“坏单词”
首先,他们被放入一个列表
,如果一个单词在这个坏单词列表中,那么“文章”将被逐字扫描。在Python中,
中的操作符测试成员资格。对于无序列表,没有比扫描整个列表更好的方法了
第二种方法使用set
数据类型,该数据类型由坏字列表初始化。集合
没有顺序,但如果包含元素,则查找速度会更快(再次使用in
关键字)。这似乎是你需要知道的全部
在我的机器上,计时为:
using list
1421499228.707602
1421499232.764034
using set
1421499232.7644095
1421499232.785762
因此,使用列表大约需要4秒,使用集合大约需要百分之二秒。您需要一个Bag
数据结构来解决此问题。在包中
数据结构元素没有顺序,但设计用于快速查找包中的元素
。It时间复杂度为O(1)
。因此,对于一篇文章中的N个单词,其总体复杂性是O(N)
。在这种情况下,哪一个是您能达到的最佳效果。JavaSet
是Java中的Bag
实现的一个例子。即使是一个愚蠢的O(n^2)
搜索算法(我认为还没有人发明过这样的东西,但仍然)也能够在很短的时间内完成,因为200和2000个单词只是一小部分数据。因此,在性能被证明降级之前,您实际上不需要担心性能。然而,通常用于存储无序数据集的数据结构是哈希表。您的目标语言是什么?其中很多都有内置的集合和/或映射,可能是通过哈希表实现的。哈希表具有更好的渐近复杂性…@TheParamagneticCroissantset
更容易实现,也更容易理解。我不认为,OP想读整本书——我不认为它会“更容易理解”——你不必给你的哈希表命名哈希表
——如果你按语义命名你的数据结构,你可以称它为单词集
。至于实现的易用性——这主要是主观的……一个具有链式冲突解决方案的简单哈希表与一个简单的二叉搜索树一样容易实现。(更好的是,像红黑树这样的高级自平衡BST实际上比高效的开放寻址哈希表更难实现。)@哈希表的参数化牛角面包伪相似复杂性是O(n)
和?BST也是如此。同样,通常重要的是平均大小写复杂度。但哈希表的伪复杂度是O(n)
。Set总是给出O(log_2(n))
“单个操作的复杂度是O(n)。这很有意义:如果所有键都有相同的哈希,那么它们都进入相同的bucket,这只是一个数组或一个链表,所以需要线性搜索。”@Ty221二叉树有log_2复杂度,Set也可以用哈希表实现。