在我的一个算法中,我使用了Ruby的combination和permutation方法。我必须讨论这种算法的复杂性。我在哪里可以找到有关其复杂性/实施的信息?
我尝试过一个简单的手工制作的'功能,但Ruby似乎在接近恒定的时间运行!
非常感谢任何关于去哪儿的信息。
答案 0 :(得分:1)
实施可以显示在您链接的相同页面上。将鼠标悬停在组合/置换方法的名称上,然后选择click to toggle source
。
您可以在主仓库中查看最新和不同版本的来源:http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/
您可以阅读array.c
的修订历史记录,以查看可能/何时对组合/置换方法进行任何更改的原因。 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/array.c?view=log。这可能会让您了解开发人员的复杂性和设计选择。
您甚至可以向消息来源的某些贡献者询问他们为什么让XYZ改变方法的原因,他们可能/可能没有帮助。
答案 1 :(得分:1)
Ruby语言规范中没有任何内容要求实现者保证某种算法的复杂性,并且肯定没有什么能够强制实现特定的实现。
每个Ruby执行引擎都有自己的实现,它们可能有也可能没有相同的算法复杂性。
例如,Rubinius的kernel/common/array.rb#L360-394
实施kernel/common/array.rb#L935-969
位于kernel/common/array.rb#L971-994
:
Array#combination
def combination(num)
num = Rubinius::Type.coerce_to num, Fixnum, :to_int
return to_enum(:combination, num) unless block_given?
if num == 0
yield []
elsif num == 1
each do |i|
yield [i]
end
elsif num == size
yield self.dup
elsif num >= 0 && num < size
stack = Rubinius::Tuple.pattern num + 1, 0
chosen = Rubinius::Tuple.new num
lev = 0
done = false
stack[0] = -1
until done
chosen[lev] = self.at(stack[lev+1])
while lev < num - 1
lev += 1
chosen[lev] = self.at(stack[lev+1] = stack[lev] + 1)
end
yield chosen.to_a
lev += 1
begin
done = lev == 0
stack[lev] += 1
lev -= 1
end while stack[lev+1] + num == size + lev + 1
end
end
self
end
位于{{3}}:
Array#permutation
如您所见,它委托给{{3}}中定义的名为def permutation(num=undefined, &block)
return to_enum(:permutation, num) unless block_given?
if undefined.equal? num
num = @total
else
num = Rubinius::Type.coerce_to num, Fixnum, :to_int
end
if num < 0 || @total < num
# no permutations, yield nothing
elsif num == 0
# exactly one permutation: the zero-length array
yield []
elsif num == 1
# this is a special, easy case
each { |val| yield [val] }
else
# this is the general case
perm = Array.new(num)
used = Array.new(@total, false)
if block
# offensive (both definitions) copy.
offensive = dup
Rubinius.privately do
offensive.__permute__(num, perm, 0, used, &block)
end
else
__permute__(num, perm, 0, used, &block)
end
end
self
end
的{{1}}辅助方法:
private