我怎样才能用另一种语言(也许C++)实现Python集
How can I implement Python sets in another language (maybe C++)?
我想将一些我已经编写的Python代码翻译成C++或其他快速语言,因为Python的速度不够快,无法完成我想做的事情。然而,有问题的代码滥用了 Python 集的一些令人印象深刻的功能,特别是我在性能关键循环中发送垃圾邮件的平均 O(1) 成员资格测试,我不确定如何在另一种语言中实现 Python 集。
在 Python 的时间复杂度 Wiki 页面中,它指出集合平均具有 O(1) 成员测试,在最坏情况下为 O(n)。我使用 timeit
亲自对此进行了测试,并对 Python 集进行成员资格测试的速度如此之快感到惊讶,即使是大 N。我查看了这个 Stack Overflow 答案,看看C++集合在使用find
操作时如何比较,以查看元素是否是给定集合的成员,它说它是 O(log(n))。
我假设find
的时间复杂度是对数的,因为C++ std 库集是用某种二叉树实现的。我认为因为 Python 集具有平均 O(1) 成员资格测试和最坏情况 O(n),它们可能是使用某种带有存储桶的关联数组实现的,这些数组可以轻松查找元素并测试它的一些虚拟值,这表明该元素不是集合的一部分。
问题是,我不想通过切换到另一种语言来减慢代码的任何部分(因为这是我首先试图解决的问题),那么我如何实现我自己的 Python 集版本(特别是只是快速成员资格测试)在另一种语言中?有没有人知道Python集是如何实现的,如果没有,谁能给我任何一般提示来指出我正确的方向?
我不是在寻找源代码,只是在寻找有助于我入门的一般想法和链接。
我对关联数组做了一些研究,我想我理解它们实现背后的基本思想,但我不确定它们的内存使用情况。如果 Python 集确实只是真正的关联数组,我如何在最少的内存使用下实现它们?
附加说明:我想要使用的相关集合将最多包含 50,000 个元素,并且集合的每个元素都将在很大的范围内(例如 [-999999999, 999999999])。
O(1)
和O(log n)
之间的理论差异在实践中意义不大,尤其是在比较两种不同的语言时。 对于n
的大多数实用值来说,log n
很小。每个实现的常量因子显然更为重要。- C++11 现在已经
unordered_set
和unordered_map
。即使不能使用 C++11,也总是有 Boost 版本和 tr1 版本(后者命名为hash_*
而不是unordered_*
)。
几点:正如已经指出的那样,你有std::set
和 std::unordered_set
(后者仅在 C++11 中,但大多数编译器都有多年来提供了类似的东西作为扩展)。 这首先是由某种平衡树(通常是红黑)实现的树),第二个作为hash_table。 哪一个更快取决于数据类型:第一种需要某种排序关系(例如 <
是否在类型上定义了它,但您可以定义自己的);这第二个等价关系(例如==
)和一个哈希与此等价关系兼容的函数。 首先是O(lg n),第二个O(1),如果你有一个好的哈希函数。 因此:
-
如果顺序比较明显快于哈希,
std::set
实际上可能更快,至少对于"较小"的数据集,其中"更小"取决于差异有多大 - 对于字符串,例如,比较通常会在第一个之后解决几个字符,而哈希代码将查看每个字符。 在我做的一个实验中(很多年前),用字符串30-50个字符,我发现盈亏平衡点约为100000元素。 -
对于某些数据类型,只需找到一个好的哈希函数,即与类型兼容可能很困难。 Python 使用哈希表来它的集合,如果您使用函数定义一个类型,则始终
__hash__
返回 1,它将非常非常慢。 编写一个好的哈希函数并不总是显而易见的。 -
最后,两者都是基于节点的容器,这意味着它们使用了很多比例如更多的内存
std::vector
,地方性很差。 如果查找是主要操作,您可能需要考虑std::vector
,保持排序并使用std::lower_bound
进行查找。根据类型,这可能会导致显着的加速,并且更少的内存使用。
- C++和带有国家符号的文件路径(也许用 UTF8 编码)
- (也许是NP-Hard)求一个集合的子集总数,使得每个子集在与其所有元素相乘时的值都大于X
- 多线程 - 降低效率,也许是由“ false共享”所产生的
- 在密钥扩展和再生成方面,AES128 和 AES256 与 AES128 和 AES256 有什么区别?(也许还有 AE
- 与基本面作斗争.特别是字符[],字符*和从数组中读取.也许我应该使用类型字符串
- 向量问题,也许有点手
- 下面的代码无法编译。也许是因为 std=c++2a 的 GCC 仍然没有完全跟上最新的草案
- 模板参数是否可以无缝匹配类型和模板,也许是可变变量的一部分
- 也许我还没有理解C++堆和堆栈的概念
- 空格很重要的另一种情况(也许?
- 重载运算符运算符<在我的类中没有被 STL 使用max_element 标准 Haskell 函数 :: (a -> 也许 a) -> a -> [a]
- C 错误,也许来自.h文件,不确定
- C字符串无法显示(也许输入)
- 一个奇怪的C++错误,也许是相对于长长类型而言的
- 堆栈超出范围.也许没有正确地称呼它
- 生命的游戏,C++-多态数组(也许还有指针)
- 清理内存(也许是win32 api)
- 也许快速错误但我不确定如何解决
- Visual Studio中可能"break the debugger"什么(也许是std::string?)
- 也许有人可以看到我缺少什么(调试案例、C++、函数指针)