本文共 1422 字,大约阅读时间需要 4 分钟。
本节书摘来自华章计算机《算法基础》一书中的第1章,第1.5节,作者:(美)罗德·斯蒂芬斯(Rod Stephens)著,更多章节内容可以访问云栖社区“华章计算机”公众号查看
在理解算法的时间复杂度上,理论很重要,由于以下几个原因,实际因素在真正的性能表现上也扮演着很重要的角色。
一个算法的分析一般认为所有的步骤都花费相同的时间,即使现实并非如此。例如,创造和摧毁一个新的对象可能比把数组中的一个整数值移动到另一位置花费更多的时间。在这种情况下,一个使用数组的算法优于一个使用许多对象的算法,即使第二个算法在大O符号中表现更好。许多编程环境也提供了访问操作系统的功能。这些功能远比基础的算法技巧高效。例如,插入排序算法的一部分要求是把数组的某些元素向下移动一个位置,以便能在它们之前插入一个新的元素。这是一个相当慢的进程,很大程度上导致了算法的时间复杂度为O(N2)。然而,许多程序可以使用现有的函数(比如.NET中的RtlMoveMemory和Windows C++中的MoveMemory)一次同时移动许多块存储内容。这些函数不是在数组中一个一个移动元素,而是一次移动许多元素,一个程序可以调用这些函数一次移动数组中一系列值,使程序更快。一个算法具有一定的理论渐近性能,并不意味着不能使用编程环境提供的工具来改善性能。一些编程环境也能提供一些工具,可以执行与书中算法相同的任务。例如,许多库包含排序例程。它们在排列数组上表现出色。C#和VB所使用的Microsoft抯 .NET Framework包含了一个Array.Sort方法。至少是一般情况下,几乎不可能用你自己的代码打败它。对于特定的问题,如果有关于数据的额外信息,仍然能够打败Array.Sort的性能。(更多的信息请阅读6.3.1节中的计数排序。)专用库也可以帮助解决某些特定问题。例如,可以使用一个网络分析库而不是编写自己的网络工具。同样的,数据库工具也可以节省很多建立树和整理数据的时间。建立自己的平衡树,可能会获得更好的性能,但是使用数据库使得工作量更少。如果你的编程工具包含着可以执行这些算法中某一个任务的功能,只管用它们。可能会获得比自己编写的算法更好的性能,也一定能减少一些调试工作。最后,最好的算法并不总是在解决大规模的问题中运行最快的那个。如果排列大量的数字,快速排序通常会提供良好的性能。但是如果只排列三个数字,一系列简单的If语句可能会有更好的性能并且简单得多。即使快速排序的性能的确更好,程序一毫秒完成排序还是二毫秒完成排序真的重要吗?如果需要多次执行排序,否则最好使用简单的、更加容易调试和维护的算法而不是使用复杂的算法去节约一毫秒。如果使用库,比如前面段落中描述的库,则可能不需要自己把所有这些敲出来,但是理解这些算法如何工作仍然有用。如果理解了这些算法,即使你没有真正编写它们。也可以更好地利用它们来完成工作,例如,如果知道了关系型数据库一般使用B树(或者类似的树)来储存它们的索引,这样将会更好地理解预分配和填充因子的重要性。如果理解了快速排序,这样就会知道为什么一些人认为.NET 框架中的Array.Sort方法在密码的角度上是不安全的(这在6.2.2节中的“使用快速排序”部分讨论)。理解算法也需要把它们应用到其他状况中。某个具体应用中可能不需要归并排序,但是可能会使用它的分治思想来解决多处理器上的其他问题。转载地址:http://eqhbo.baihongyu.com/