排序与线性搜索查找最小值/最大值

时间:2012-06-07 18:25:26

标签: perl sorting complexity-theory

最近,我在perl中遇到了以下代码,它返回所有传递参数中的最小数值。

return 0 + ( sort { $a <=> $b } grep { $_ == $_ } @_ )[0];

我通常使用简单的线性搜索来查找列表中的最小值/最大值,这对我来说似乎很简单且充分优化。以上代码是否比简单的线性搜索更好?在这种情况下与perl有什么关系?谢谢!

3 个答案:

答案 0 :(得分:4)

O()没有说算法需要多长时间。例如,在其他条件相同的情况下,我总是在以下两个中选择算法2:

  • 算法1:O(2 * N + 1000天)= O(N)
  • 算法2:O(5 * N + 100ms)= O(N log N)

O()指定算法在输入大小增加时 scale 所用的时间。 (好吧,它可以用于任何资源,而不仅仅是时间。)由于前两个答案只是用O()来讨论,所以它们没用。

如果你想知道哪种算法对于给定大小的输入更好的算法有多快,你需要对它们进行基准测试。

在这种情况下,看起来List::Utilmin 总是明显更好。

$ perl x.pl 10
           Rate  sort LUmin
sort  1438165/s    --  -72%
LUmin 5210584/s  262%    --

$ perl x.pl 100
           Rate  sort LUmin
sort   129073/s    --  -91%
LUmin 1485473/s 1051%    --

$ perl x.pl 1000
          Rate  sort LUmin
sort    6382/s    --  -97%
LUmin 199698/s 3029%    --

代码:

use strict;
use warnings;

use Benchmark  qw( cmpthese );
use List::Util qw( min );

my %tests = (
   'sort'  => 'my $x = ( sort { $a <=> $b } @n )[0];',
   'LUmin' => 'my $x = min @n;',
);

$_ = 'use strict; use warnings; our @n; ' . $_
   for values %tests;

local our @n = map rand, 1..( $ARGV[0] // 10 );
cmpthese(-3, \%tests);

答案 1 :(得分:2)

你是对的。如果您不需要将排序数据用于任何其他目的,则简单线性搜索最快。为了完成它的工作,无论如何,排序必须至少查看一次每个数据。

只有当排序的数据对其他用途有用时 - 或者当我不关心运行时间,功耗,散热等 - 我才会对数据进行排序以找到最小值和最大值。 / p>

现在,@ SimeonVisser是正确的。排序确实有 O(n * log(n))。 这并不像许多程序员想象的那样慢于 O(n)在感兴趣的实际情况中,管理排序的平衡二叉树(或其他此类结构)的开销可能与 log(n)因子一样重要。所以,人们不必因排序的前景而惊恐万分!但是,线性搜索仍然更快:你对此非常正确。

此外,@ DavidO添加了这样一个富有洞察力的评论,我会用他自己的话来引用它:

  

线性搜索也是一种更容易概括的算法。例如,线性搜索可以容易地(并且相对有效地)基于磁盘用于大数据集。而基于磁盘的排序变得相对昂贵,而如果不是字段大小则更复杂   归一化的。

答案 2 :(得分:0)

线性搜索是O( n ),原因很明显。排序为O( n log n )(请参阅Perl文档中的sort)。所以是的,线性搜索在复杂性方面确实更快。这不仅适用于Perl,也适用于任何实现这些算法的编程语言。

与许多问题一样,有多种方法可以解决它,并且还有多种方法可以获得列表的最小值/最大值。从概念上讲,当你只想要列表的最小值或最大值时,线性搜索会更好,因为问题不会要求排序。