所有迭代算法都可以递归表达吗?

elj*_*nso 44 iteration recursion programming-languages language-theory

如果没有,是否有一个好的计数器示例显示迭代算法,其中不存在递归对应物?

如果所有迭代算法都可以递归表达,那么在哪些情况下更难以做到这一点?

此外,编程语言在这一切中扮演什么角色?我可以想象,Scheme程序员对Java迭代(=尾递归)和堆栈使用的看法与Java专用程序员不同.

pli*_*nth 74

有一个简单的临时证明.由于您可以使用严格的迭代结构和仅使用递归结构的转换完整语言来构建图灵完整语言,因此这两者是等价的.

  • C鲍尔:事实上,事实并非如此.证明非常容易:假设语言IT(仅使用迭代构造)和REC(仅使用递归构造).使用IT模拟通用图灵机,然后使用REC模拟通用图灵机.模拟器程序的存在保证了IT和REC都可以计算所有可计算的功能.此属性已经过lambda演算证明,其中所有函数都是部分递归的. (7认同)
  • 哇,深思熟虑.我羡慕所有比我更快消化的人.是时候阅读了这篇文章. (5认同)
  • 或者,使用严格(迭代/递归)构建图灵完整语言,并在其中使用严格(递归/迭代)为图灵完整语言编写解释器.Voila,无论你编写什么程序,都是在迭代和递归的同时执行! (2认同)

Nor*_*sey 18

所有迭代算法都可以递归表达吗?

是的,但证据并不有趣:

  1. 其所有的控制流转换程序转换成包含单个case语句的单个循环,其中每个分支是直线控制流可能包括break,return,exit,raise,等.引入一个新变量(称之为"程序计数器"),case语句用它来决定下一个要执行的块.

    这种结构是在20世纪60年代伟大的"结构化编程战争"中发现的,当时人们在争论各种控制流构造的相对表现力.

  2. 用递归函数替换循环,并用参数替换每个可变局部变量到该函数.瞧!迭代由递归替换.

此过程相当于为原始函数编写解释器.正如您可能想象的那样,它会导致无法读取的代码,并且这不是一件有趣的事情. 然而,一些技术对于具有命令式编程背景的人来说是有用的,他们正在学习第一次用功能语言编程.


Chr*_*ung 8

就像你说的,每个迭代方法都可以变成一个"递归"方法,并且通过尾调用,堆栈也不会爆炸.:-)实际上,这实际上是Scheme如何实现所有常见的循环形式.方案示例:

(define (fib n)
  (do ((x 0 y)
       (y 1 (+ x y))
       (i 1 (+ i 1)))
      ((> i n) x)))
Run Code Online (Sandbox Code Playgroud)

在这里,虽然功能看起来迭代的,它实际上在递归内部拉姆达这三个参数,x,y,和i,并在每次迭代新值自称.

这是函数可以宏扩展的一种方式:

(define (fib n)
  (letrec ((inner (lambda (x y i)
                    (if (> i n) x
                        (inner y (+ x y) (+ i 1))))))
    (inner 0 1 1)))
Run Code Online (Sandbox Code Playgroud)

这样,递归性质在视觉上变得更加明显.

  • 并注意*任何*迭代算法都可以转换为尾递归算法.例如,只需将其转换为延续传递方式即可. (4认同)

Joh*_*han 6

将迭代定义为:

function q(vars):
  while X:
    do Y
Run Code Online (Sandbox Code Playgroud)

可以翻译为:

 function q(vars):
    if X:
      do Y
      call q(vars)
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,Y会包括递增一个由X测试的计数器.当进行递归路由时,这个变量必须以某种方式在'vars'中传递.