最快的数据结构,按顺序返回一系列项目

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最快的数据结构,按顺序返回一系列项目相关的知识,希望对你有一定的参考价值。

我正在研究一个leet问题,我只是为了它的乐趣而这样做。我想我可以尽可能地解决问题的所有测试输入。所以说,我提前知道了所有的输入。什么是最快的结构返回解决方案。

我尝试使用dict将所有输入映射到所谓的解决方案。

class DictSolution():
    DATA = {x:x for x in range(1000000)}

    def compute(self, x):
        return self.DATA[x]

然后,我想,因为我知道输入将以什么顺序进行测试,所以我不需要“查找”。所以我尝试使用set并忽略所有输入。

class SetSolution():
    DATA = {i for i in range(1000000)}

    def compute(self, x):
        return self.DATA.pop()

令我惊讶的是,它比dict略慢,每次减慢1-2%。顺便问一下,这是我如何计时。

def test_dict():
    sol = DictSolution()
    for i in range(1000000):
        sol.compute(i

ds = timeit.timeit(test_dict, number=1)
ss = timeit.timeit(test_set,  number=1)
print ("Dict Solution:", ds)
print ("Set  Solution:", ss)

>> Dict Solution: 0.11734077199999998
>> Set  Solution: 0.11939082499999998

问题:

  1. 为什么set会变慢?
  2. 从逻辑上讲,按顺序返回内容应该比在表格中查找内容更快。所以我不相信dict方式已经是最快的。我能做些什么才能获得更好的时间?
答案

我相信来自@schwobaseggl的建议是正确的。来自here,访问元素的复杂性是O(1)dictlist,这在某个question中有所复制,实际上在之前的设置中listdict快得多。我复制了您的基准测试,并完整地添加了其他数据结构:

  • 名单
  • 字典
  • 设置(使用pop)
  • 和(从集合)
  • 元组

代码:

import timeit
from collections import deque


class DictSolution:
    DATA = {x: x for x in range(1000000)}

    def compute(self, x):
        return self.DATA[x]


class SetSolution:
    DATA = {i for i in range(1000000)}

    def compute(self, x):
        return self.DATA.pop()


class DequeSolution:
    DATA = deque(i for i in range(1000000))

    def compute(self, x):
        return self.DATA.popleft()


class ListSolution:
    DATA = [i for i in range(1000000)]

    def compute(self, x):
        return self.DATA[x]


class TupleSolution:
    DATA = tuple(i for i in range(1000000))

    def compute(self, x):
        return self.DATA[x]


def test_dict():
    sol = DictSolution()
    for i in range(1000000):
        sol.compute(i)


def test_set():
    sol = SetSolution()
    for i in range(1000000):
        sol.compute(i)


def test_deque():
    sol = DequeSolution()
    for i in range(1000000):
        sol.compute(i)


def test_list():
    sol = ListSolution()
    for i in range(1000000):
        sol.compute(i)


def test_tuple():
    sol = TupleSolution()
    for i in range(1000000):
        sol.compute(i)


def test_pop_list():
    sol = PopListSolution()
    for i in range(1000000):
        sol.compute(i)


des = timeit.timeit(test_deque, number=1)
ss = timeit.timeit(test_set, number=1)
ds = timeit.timeit(test_dict, number=1)
ls = timeit.timeit(test_list, number=1)
ts = timeit.timeit(test_tuple, number=1)
times = [("Dict Solution:", ds), ("Set Solution:", ss), ("Deque Solution:", des), ("List Solution:", ls), ("Tuple Solution:", ts)]

for label, time in sorted(times, key=lambda e: e[1]):
    print(label, time)

产量

Tuple Solution: 0.1597294129896909
List Solution: 0.16653884798870422
Dict Solution: 0.17414769899914972
Set Solution: 0.190879073983524
Deque Solution: 0.1914772919844836

我运行了几次脚本,结果类似于元组解决方案和列表解决方案交替导致。请注意,SetSolutionDequeSolution都是最慢的。那么回答你的问题:

  1. setdeque都比较慢,因为你要从列表中删除一个元素,在其他结构中你只访问元素。
  2. 这在前面的答案中得到了部分回答,pop不仅从数据结构中返回一个元素,还从中删除元素。所以我希望更新数据结构比访问其中一个元素要慢。

注意虽然popset一起用于测试用例,但通常不会出现这种行为,例如:

test = {'e' + str(i) for i in range(10)}
while test:
    print(test.pop())

输出(设置弹出)

e5
e8
e6
e0
e1
e3
e7
e4
e9
e2

有关此主题的更多信息,请访问here

我还使用list.pop(0)对解决方案进行了基准测试,尽管使用的是较小的范围:100000,以及较少的候选者(列表,元组和字典)。结果如下:

('List Solution:', 0.018702030181884766)
('Tuple Solution:', 0.021403074264526367)
('Dict Solution:', 0.02230381965637207)
('List Pop Solution', 1.8658080101013184)

基准测试是在以下设置上运行的:

Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz
16GB
Ubuntu 16.04
Python 3.5.2
另一答案

dict是最快的查找数据结构,因为它是使用哈希表实现的:它几乎需要一段时间来查找哈希表中的键。请查看以下链接以获取更多信息:

This pdf from MIT explains the subject

以上是关于最快的数据结构,按顺序返回一系列项目的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 将项目添加到排序数组的最快方法

html 将以编程方式附加外部脚本文件的javascript代码片段,并按顺序排列。用于响应式网站,其中ma

在 c++ 中加快 map<string,int> .find() 的最快方法。键按字母顺序排列的位置

以最快的方式重新排序字母以按字典顺序排在第一位

在 Pyspark 中按顺序应用多个正则表达式进行文本清理的最快方法

那种鼠标连点器,设置几个位置,然后按顺序点击的那种