自定义设计算法的优点

Benefits of Custom Designed Algorithms

本文关键字:算法 计算 自定义      更新时间:2023-10-16

在许多语言中,特别是Java和C++,都有一个庞大的标准库。计算机科学、搜索、排序、哈希等领域的许多经典问题都在这个库中实现。我的问题是,与简单地使用库的版本相比,实现自己的算法有什么好处吗?如果这是真的,有什么特别的例子吗?

我之所以这么问,是因为在学校里,大量的时间都花在了排序上,但在我的实际代码中,当人们已经在Java和C++中实现并优化了排序算法时,我找不到利用这些知识的理由。

编辑:我和我认识的一位教授详细讨论了这个问题,我发布了他的回应,有人能想出更多的补充吗?

大多数时候,库存库函数的性能将比您自定义的任何代码都要高。

如果你有一个高度特定的(而不是一般的)问题,你可能会发现通过编码一个专门的函数来提高性能,但作为一名开发人员,你应该有意识地努力不要"重新发明轮子"。

排序是一个很好的例子。如果除了如何比较元素之外,您对要排序的数据一无所知,那么标准排序算法会很好。在这种情况下,在C++中,STL排序会做得很好。

但有时你对自己的数据了解得更多。例如,如果数据由均匀分布的数字组成,则基数排序可以更快。但基数排序是"侵入性的",因为它需要更多地了解你的数据,而不仅仅是一个数字是否比另一个大。这使得编写一个可供所有人共享的通用接口变得更加困难。所以STL缺少基数排序,对于这种情况,您可以通过编写自己的代码来做得更好。

通常,标准库包含用于解决非常常见问题的非常快速的代码。如果你有一个特定的问题,在很多情况下你可以做得比图书馆更好。当然,你最终可能会遇到一个图书馆无法解决的复杂问题,在这种情况下,你从研究已解决问题的解决方案中获得的知识可能是非常宝贵的。

在大学或学校,或者如果你是一名娱乐程序员,你将被鼓励(或者在我强烈的意见中,你应该)自己实现这些东西的子集。为什么?学习。对我来说,实现一个已经发明的重要轮子(B树)是我大学时代最具影响力的经历之一。

当然,我同意作为一名开发人员,你应该努力不重新发明轮子,但当通过形成性经验学习时,不同的规则会适用。我在这个论坛的其他地方读到,要使用抽象级别N的东西,有一个关于抽象级别N-1的工作知识并熟悉级别N-2是一个非常好的主意。我同意。除了形成性之外,当你确实遇到库存库不适合的问题时,它还为你做好了准备。相信我,这可能发生在你50年的职业生涯中。如果你正在学习data structures等基础知识,其中最终目标不是完成产品的完整性,而是自我改进,那么花时间"重新发明轮子"是很好的。

前代数/代数/三角学/微积分值得学习吗?

我不知道这是一个"我在学校浪费时间/金钱吗"的问题,还是一个关于你自己的版本是否会更好的真诚问题。

至于在学校浪费时间/金钱:如果你只想在开发一个有用的应用程序时大做文章,那么你学习这些已经实现的算法绝对是在浪费时间——你只需要把一些有效的东西拼凑在一起。

另一方面,如果你想做一些真正重要的东西,需要快速,并且需要成为正确工作的正确工具——那么它通常还不存在,你会回到像Stack Overflow这样的网站,问一年级或二年级的计算机科学问题,因为你对现有技术不够熟悉,无法推出自己的变体。

根据我的工作,我一直是两面派。我需要快速开发它,还是它必须运行良好?对于快速应用程序编程,它有大量的库存函数,除非有性能或功能方面的障碍,我绝对必须解决。对于专业游戏编程来说,它必须运行得非常快。这就是真正的知识进入内存管理、IO访问优化、计算几何、低级别和算法优化以及各种巧妙的乐趣的时候。而且它很少是一个股票实现来完成这项工作。

我在学校学到了大部分吗?不,因为我已经知道了其中的大部分,但毫无疑问,这些学位会有所帮助。另一方面,你不知道其中的大部分(否则你不会问),所以是的,简而言之:这是值得的

一些具体的例子:

  • 如果你想制作真正令人惊叹的游戏,那就用实时呼吸算法,这样你就可以对其他人做不到的事情进行编码。如果你想制作一些不太令人惊叹的有趣游戏,可以使用股票代码并专注于设计。这是有限的,但它的发展速度更快。

  • 如果你想对嵌入式设备(一个相当大的市场)进行编程,通常库存代码是做不到的。通常存在库实现无法满足的代码或数据内存限制。

  • 如果你需要普通硬件的服务器性能,股票代码是不行的

  • 如果你想做任何有趣的手机开发,资源紧张需要你变得聪明,即使是对于"无聊"的应用程序。(用户体验就是一切,对大部分数据的股票排序功能通常太慢了。)

  • 通常,你被限制使用的库并不能满足你的需要。(例如,C#没有一个"稳定"的排序方法。我一直遇到这种烦恼,并编写了自己的解决方案。)

  • 如果你要处理大量的数据(现在大多数企业都有),你最终会遇到接口太慢的情况,需要一些巧妙的解决方案,通常需要很好地使用自定义数据结构。

这些库为您提供了运行良好的测试实现,因此经验法则是使用这些实现。如果你有一个非常特殊/复杂的问题,你可以使用一些领域知识,那么你就需要实现自己版本的算法。

我记得Bill Pugh在编程语言课上举的一个例子,他们分析了复杂应用程序的性能,并意识到程序员对排序算法的错误自定义实现(该代码在应用程序的实际运行中多次使用)导致了90%的性能下降!

在与计算机科学教授详细讨论后,以下是他的意见:

使用库的理由

1.您正在编写带有截止日期的代码。

  • 阻碍你快速及时地完成一个项目的能力是没有意义的。这就是为什么图书馆毕竟是为了节省时间和避免"重新发明轮子"而编写的

2.如果您想充分优化代码。

  • 很可能,用Java或C++或任何人的库编写算法的非常有才华的团队在为该语言优化算法方面做得比你一两个小时所能做的要好得多。或者四个

3.您以前已经解决了这个问题。

  • 如果你已经解决了这个问题,并且对它的设计有了很好的全面了解,你就不需要为复杂的解决方案而努力,因为你不会获得太多好处

话虽如此,仍然有许多理由制定自己的解决方案。

自己动手的理由

1.一旦你遇到了一个通过非库解决方案更好地优化的问题,就完全有必要对问题解决技术和算法有基本的了解。

  • 如果你有一个高度特定的问题,在处理网络或游戏等问题时经常会出现这样的问题。能够发现特定算法优于库版本的情况变得非常宝贵

2.对算法及其设计和使用有很好的理解会让你在工作中更有价值。

  • 任何一个半吊子的程序员都可以编写一个函数来比较两个对象,然后将它们放入库函数中,然而,能够发现情况并最终提高程序功能和速度的函数将受到管理层的重视

3。拥有如何做某事的概念通常与能够做某事一样有价值。

  • 凭借对Java库以及如何使用它们的卓越知识,您很有可能在Java中解决任何问题并取得合理的成功。然而,当你被雇佣到二郎工作时,你将面临一些艰难的时期。如果你知道Java的库是如何做的,而不仅仅是做什么,你就可以把这些想法转移到任何语言中

4.作为程序员,我们从来不会真正满足于仅仅拥有一些"工作"。

  • 很可能你很想明白为什么事情会成功。正是这种好奇心驱使你去研究这个领域。不要否认这种好奇心!鼓励它,尽情学习

5.最后,创建自己的排序或哈希等个人方式会带来巨大的成功感和成就感。

  • 想象一下,当你宣布你可以在n log(n)时间内找到两个顶点之间的最短路径时,你的朋友会多么酷!严肃地说,知道自己完全有能力理解并根据知识选择最佳解决方案是非常有益的。不是图书馆给你的