译者:飞龙
自豪地采用谷歌翻译
这几乎完全是视频练习,其中我演示了如何改进你至今为止编写的代码的性能,但首先你应该尝试它。你已经分析了 练习 18 的代码的速度有多慢,所以现在是时候实现你的一些想法。修复简单的性能问题时,我会给你一个简单的列表来寻找和修改:
sorted.py
和其他数据结构中的count()
函数是一个很好的例子。你可以在函数内跟踪数据结构的大小。每次添加时,你可以增加它,并且每次删除时,减少它。每次都不需要遍历整个列表。你还可以使用这个预先计算的计数,通过检查count == 0
来改进其他功能的逻辑。DoubleLinkedList
来演示这个问题。字典需要随机访问元素,至少是桶的列表中的元素。使用DoubleLinkedList
的DoubleLinkedList
意味着每次你想访问第 n 个元素,你必须遍历所有元素直到 n。用 Python 列表替换它将大大提高性能。这是一个练习,使用现有代码从更简单的数据结构中构建数据结构,因此不一定是实现最好的 Python Dictionary
(它已经有一个了)的练习。list
之类的数组却不是很好。快速排序对于list
更好,但在链接的数据结构上不是很好。DoubleLinkedList
中,你将经常从桶的开头开始,并在槽中搜索一个值。在当前的代码中,这些槽进来时,你简单地添加它们,这可能是随机的也可能不是。如果你采取了一个规则,在插入时排序这些列表,那么寻找元素会更容易和更快捷。当槽的值大于你要查找的值时,你可以停止,因为你知道它是有序的。这样做使得插入速度更慢,但使几乎每一个其它操作变快,因此要为练习选择正确的设计。如果你需要执行大量的插入,那么这不是很机智。但是,如果你的分析显示,你需要执行很少的插入,但是很多的访问,这是个加速的不错方式。Dictionary
和 Python 内置类型list
比较,看看你可能有多少优势。merge_sort
代码可以通过给它一个比 Python 堆栈更大的列表,来使其崩溃。尝试给它一些丧心病狂的东西,例如 3000 个元素的列表,然后慢慢地减少元素数量,直到找到导致 Python 耗尽堆栈的极限值。Python 不执行某些递归优化,所以没有特别考虑的递归会像这样失败。在这种情况下,重写merge_sort
来使用循环会更好(但要困难得多)。在练习 18 的分析过程中,你应该有了一些很大的收获。现在你的任务是尝试实现它们,以及提升代码的性能。
尝试使用你的分析和上述建议性改进的描述,来系统地提升代码的性能。“系统地”的含义是,使用锁定步骤控制的方法来完成,使用数据来确认你已经改进了一些东西。这是你在此练习中遵循的流程:
你应该研究 Tim Sort 的原始邮件,最后研究由 EU FP7 ENVISAGE 研究人员在 2015 年发现的错误。原始电子邮件于 2002 年发送,随后实现。这个 bug 发现了 13 年了。当你去实现自己的算法想法时,记住这一点。即使大型项目的顶尖开发人员也会在它们的算法中遗留 bug,它们很长时间都没有发现。另一个例子是 OpenSSL 项目,它几十年来一直存在 bug,因为每个人都相信“专业密码学家”创建了代码。原来,即使是所谓的专业密码学家也可以写出糟糕的代码。使新的算法正确需要特殊技能,并且我认为 -- 使用定理证明工具来验证正确性。除非你有这样的背景,创造新的算法和数据结构可能会产生危险。这包括加密算法和加密网络协议。只要你掌握实现技能,实现其他人已经证明的算法完全正常,运行良好。但是不要在没有一些帮助的情况下制作自己的头发数据结构。实现其他人已经证明的算法完全没问题,并且是个好的练习。但是不要在没有一些帮助的情况下制作自己的粗制滥造的数据结构。