高阶函数的计算复杂性?

tai*_*ion 4 complexity-theory haskell functional-programming higher-order-functions

映射和过滤器看起来像线性O(n),因为它们只需要遍历列表一次,但它们的复杂性是否受到传递的函数的影响?例如下面两个相同顺序的例子?

map (+) list

map (complex_function) list
Run Code Online (Sandbox Code Playgroud)

Meh*_*dad 5

你似乎有一个(常见的)误解,即复杂性是一个函数n.

什么是n

n只是一个参数来衡量你的输入.它可能不足以(或甚至是必要的)统计数据来描述您的输入 - 您可能需要其他变量来准确描述输入的复杂性.

所以,map并且filter是线性n.它们对其他变量的依赖取决于你传递的函数,但它们的依赖性n通常不会.

(脚注:是的,你可以传递一个函数,map并且filter在处理更多元素时实际执行更多的工作,但这是无趣的,除了我想在这里做的点.)


chi*_*chi 5

在几乎所有情况下,当高阶函数的文档表明其复杂性时O(f(n)),这假设高阶函数具有恒定的时间复杂度O(1).此外,确切的含义n可以变化,但是当没有明确说明时,应该从上下文中清楚地看出:例如列表的长度,集合/映射中的元素/关联的数量,等等.

假设我们有一个高阶函数g称为g h ...那里h是一个功能,而...首先订单数据.如果没有关于高阶函数的任何其他信息g,如果文档说明了它O(f(n)),你可以得到一个更现实的最坏情况界限,O(f(n)) * CostH其中CostH代表调用H一次的成本.

当然,CostH还将取决于哪些参数开始传递给h:在这里,我们所知道的是这些参数正在O(f(n))及时构建.h因为,例如,如果h将树作为输入,那么很难在参数的大小上获得有用的一般约束,那么您可以在短时间内构建一个非常大的树:

foo :: Int -> Tree ()
foo 0 = Tree []
foo m = Tree [t,t] where t = foo (m-1)
Run Code Online (Sandbox Code Playgroud)

以上构建了一棵2^m树叶m及时(感谢分享).这可以适应3^mb^m平凡地保持b*m复杂性.

但是,可能有一些方法可以利用参数化来恢复更有用的界限.例如,如果我们的订单功能有类型

g :: (a -> Int) -> [a] -> Int
Run Code Online (Sandbox Code Playgroud)

那么我们知道g h [...]只能调用h从列表中获取参数.类似地,库函数调用sortBy h [...]只能用于h比较提供的列表中的两个元素.

然而,我不知道如何形式化和证明上述草拟的权利要求.很可能有一些关于这个主题的研究论文.