为什么我十几岁时写的代码很糟糕:排序算法和大 O 符号

当我 15 岁左右时,我

有一周的“工作体验”。美国人会称之为“实习”,但其实不然:工作体验是英国学校的一种活动,基本上就是让年龄较大的孩子离开学校几天,然后把他们交给当地的企业,这样老师们就可以休息一下了。

我现在记不起这家

公司的名字了,但无论如何,他们遇到了一个问题:他们最近扫描了大量照片,记录了这个地方的所有历史,但这些照片没有分类:他们只有几百张,也许几千张照片。都在一个文件夹中,文件名随意。工作经验的孩子被分配了一项工作,即浏览所有这些照片并撰写描述。“嗯,这很无聊”,我想,因为我当然是这么想的。这真的很无聊。这是你给工作经验的孩子的工作,因为他们对这个世界还没有足够失望。

因此,在输入描述

在尼泊尔,移动数据通过 4G 网络,尼泊尔提供价 荷兰移动数据 格低廉、覆盖范围不断扩大的移动数据服务。城市地区享有可靠的接入,但在农村和山区连接存在问题。尼泊尔的电信运营商提供灵活的数据选择,政府正在尝试升级其基础设施,以全面改善移动数据服务,包括推出 5G。

的同时,我想我应该炫耀一下,并编写一个系 您的营销策略适合当今的市场吗? 统来搜索它们。它会像雅虎,或者那个开始流行的新谷歌。它看起来很棒。我看起来真的很聪明。我对如何构建它一无所知,但带着完全没有根据的自信,我认为这不会是一个大问题。事实并非如此。输入搜索词,循环遍历所有描述,计算匹配的单词数,然后返回所有匹配的结果,按匹配数排序。是的。它工作得很好。直到我得到了大约五十张照片。这时它开始变得有点慢。一百张之后,它开始变得非常慢。我开始花更多时间试图修复它,而实际做我工作的时间却更少了。实际上,我的意思是,我没有得到报酬,所以……无论如何,为了解释为什么我的代码很糟糕:让我们谈谈大 O 符号。

无论您编写什么代

码,几乎肯定有许多不同的方法来解决问题。但即使所有这些方法最终都能得到相同的结果,它们可能需要大量不同的时间或内存才能实现。最好的例子就是排序。所以我们有一堆不同大小的块,我们有一个列表。我们可以使用什么算法来对列表进行排序?

让我们从冒泡排序

开始。取出前两个块并进行比较。如果第一个比第二个长 bmb目录 ,就交换它们。如果不是,就把它们留在原处。现在比较接下来的两个块。同样。如果它们的顺序不对,就交换它们。如果顺序正确,就把它们留在原处。以此类推,直到我们到达列表的末尾。此时,我们已经将列表中最大的块移动到了最后。就这样。虽然效率不高,但现在已经完成了。所以现在我们可以从头开始:我们可以比较,如果需要就交换,比较,如果需要就交换,比较,如果需要就交换,等等,等等,如果我们从头到尾都没有移动任何东西,那么我们就知道一切都已排序,我们可以停下来。如果没有:我们回到起点。最终,经过许多、许多、许多次传递后,恭喜你,我们有一个排序列表!

冒泡排序的每个块都会

“冒泡”,这很糟糕。它必须在每次传递时检查列表中的每个块,并且在大多数情况下,它必须传递与列表中的块数相同的次数。十个块意味着十个操作,执行十次。一百个块意味着一百个操作,执行一百次。它必须执行的操作数与块数的平方成正比。这意味着它有一个O(n²)

大 O 符号以及 O 符号的基础是由 19 世纪末研究解析数论的德国数学家奠定的。但它是由伟大的 Donald Knuth 在 20 世纪 70 年代在计算机科学领域推广的。“Ka-nooth”?我应该检查一下。无论如何。大 O 将算法提炼为一个表达式,该表达式表示在添加更多块、更多任何类型的输入时算法的性能。它可以让您从大局上大致比较算法在增加更多复杂性时会变得多慢。

意味着处理时间会随着输入数量的平方而增加:输入数量增加一倍,运行时间增加四倍。算法可以合理拥有的最低大 O 符号是“常数”。O(1)这意味着无论你向它投入多少东西,它都会在相同的时间内返回答案。并且O(1)通常是一些非常简单的东西,例如“返回列表中的第一个项目”。

一些常见算法具有O(n) 或“线性”。这意味着处理时间会随着项目数量的增加而稳步增加。因此,如果您的代码需要遍历列表并对其中的每个项目执行一项操作:那就是线性的。项目数量增加一倍,处理时间也会增加一倍。

那么让我们尝试一些其他

排序算法。’插入排序’:从第二个项目开始,将其与前一个项目进行比较。如果它们的方向错误,则交换它们。现在取第三个项目,并将其与前一个项目进行比较:如果它们的方向错误,则交换它们,然后再与前一个项目进行检查。基本上,你继续依次将每个项目移向起点,边走边检查,直到你找到更小的东西并且你知道它在正确的位置,或者你到达列表的开头并且你知道它是最小的。如果你有一手牌并且你按数字顺序排列它们,那么你可能不假思索地使用了这种算法。是的,这通常比冒泡排序更快。但至关重要的是,它的大 O 符号也是O(n²)。这是一个非常重要的区别:如果两种算法具有相同的大 O,并不意味着它们的性能相同。这只是意味着,如果你绘制它们随着输入的增加而变差的图表,这些图表具有相同的形状。对于冒泡排序和插入排序,如果将项目数量加倍,则运行时间将增加四倍:但对于插入排序,运行时间通常一开始就较短。

我不会详细介绍每种

排序算法,因为排序算法有很多,但我想提一下两种。第一种是快速排序。选择列表中的一项并将其称为“枢轴”。然后浏览列表,将任何小于枢轴的元素放在其左侧,将任何大于枢轴的元素放在其右侧。完成后,只查看枢轴左侧的元素并执行相同操作,选择一个枢轴并将它们拆分。一直向下重复该分治过程。然后对每个枢轴点的另一侧执行相同操作,然后向上返回。最坏情况下的 Big O 符号仍然是。但随机列表上的平均性能是O(n log n)。我不会深入研究数学,但可以说这要好得多。

而另一方面,还有 bogosort,它的设计初衷就是为了搞笑。Bogosort 非常简单:随机化列表。它排好序了吗?好!如果没有,再次随机化并继续,直到排好序。它的平均性能是O((n+1)!)。阶乘。您可以绘制所有常见大 O 符号的图表来比较它们。但重要的是:您编写的任何代码的大 O 都将主要受到其中最差的一个的影响。如果您的代码执行十个线性操作和一个大 O 为 的操作:那么,您的程序现在就是。请记住,这只是一个近似值,它是人类确定最佳使用算法的指南。尽管是关于计算机科学的,但它还是有点模糊。

那么,当我还是个孩子的时候,我应该对我的搜索系统做些什么呢?好吧,我可以使用已经存在的代码,意识到其他人已经为我完成了这项工作。这是真的。但最终我应该做的是客户要求的:将描述输入文字处理器并将其保存为文档。因为这是一个更好的解决方案:他们只需按 Control-F 即可搜索。当操作系统升级时,文本不会崩溃或需要更新。如果他们有新照片要添加,任何知道如何打字的人都可以更新它。他们今天仍然可以打开那个文档。最大的问题不是我使用了糟糕的算法:最大的问题是我忽略了用户真正需要什么,因为我想炫耀我自认为有多聪明。当然,考虑事情会以多快的速度运作很重要,但最好的解决方案并不总是最快的,也不是最聪明的。它是适合所有人的长期解决方案。

 

编程 代码 大 O 符号 算法
如果您发现文中存在错误,请选择错误并按 Ctrl-Enter 向作者发送消息。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部