递归函数论与程序设计的关系
(刘爱贵 高能物理研究所计算中心 北京 2003年)
摘要
: 递归函数论是元计算机科学理论基础,它与计算机科学的实践紧密相关。递归思想影响了程序设计语言的构造,甚至影响了计算机系统结构。本文根据递归函数类的构造过程来论证递归与程序设计语言基层控制机制的关系,以及递归思想对计算机科学其他一些方面的影响。
关键词
: 递归定义 复合 原始递归 极小化 结构化程序设计 递归过程 栈
可计算性理论是计算机科学的理论基础之一,递归函数论和图灵机是其两大理论支柱。图灵机是一种抽象计算机,它为可计算数的计算提供了强的有力的计算手段,是计算机的雏形和冯.诺依曼计算机的理论模型,影响了传统计算机的设计思想。递归函数理论作为元计算机科学理论基础,明确了计算机可计算的对象——递归函数类。图灵论题:一个函数是可计算的当且仅当图灵机是可计算的。而图灵机可计算的函数正是递归函数类,确切地说是一般递归函数类。图灵机和递归函数论有着天然的联系。递归函数论与计算机科学的实践有着密切的关系,递归的思想直接影响了程序设计语言的构造,进一步影响了计算机系统的结构。
递归是一种定义对象类的方法,这个方法称为递归定义。存在一定的原始对象,在被定义的类中,我们给出一些方法,运用这些方法要给定某些已知在类中的对象中,可以产生类中的新对象。被定义的类中的全体成员恰好而且仅仅是那些由原始对象开始,反复使用所给定的获取新对象的规则而引进的新对象。这种定义类的方法称为递归定义。递归函数类可以用递归来定义,它由原始对象经过复合运算、原始递归运算和极小化运算而得到。原始对象是三个最简单的原始函数:
1、继函数,S(x)=x+1。
2、零函数,N(x)=0。
3、广义单位函数,
(其中0≤i≤n)。
在这三个原始函数基础上,我们可以定义出非常丰富的函数类。运算规则有:
1、复合运算。如果已知函数
是所生成类中的成员,那么函数
是由这些函数通过复合运算得到的(图1)。
图1
的复合计算的操作
2、原始递归运算。我们称将要定义的函数为r(x)。原始递归的运算包括把某种特定的值赋给r(0),和一个由已经得到的r(k)来确定r(k+1)的过程(图2)。
图2 原始递归的运算——r(x)的计算
3、 极小化运算。对于每一个给定的全函数
引进一个新函数
,对于给定的
,新函数的值为使得
的最小的y。记作
,这样的y值可能没有定义(图3)。
图3 极小化运算——由f(y,x)计算h(x)
这三个运算能力是强有力的。原始函数通过复合生成基本递归函数类,继而根据原始递归运算生成递归函数类,再经过极小化运算即可得到部分递归函数类。由此可见复合运算、原始递归运算和极小化运算在数学体系中的关键作用,这也使得我们推想它们在程序设计中的重要性,它们与程序基层控制机制密切相关。
构造性是计算机系统的最根本特征,也是能行过程的重要特征,而递归是最具代表性的构造性数学方法。递归函数类就是递归构造得到的,而程序是构造性证明,图灵机理论已经蕴含了程序设计的思想。我们用函数方法构造一个可计算函数f(或者等价地构造性证明f是可计算的),就等于对f进行程序设计。Turing-Church论题告诉我们:递归函数类等同于能行可计算函数。而复合运算、原始递归运算和极小化运算发挥了很关键的作用,所以旨在提供通用计算功能的计算机必须实现这些运算。程序设计语言中的许多设施都是为了构造递归函数类而设置的。过程(Procedure)和宏(Macro)为运用复合提供了明显的便利。为了应付复合和原始递归运算的定义,一些程序设计语言,如ALGOL68,还提供了以函数作为输入参数和输出结果的特殊过程。这样复合运算可以解释成提供过程的功能。极小化运算实质上包含了对具有检测出口条件的循环进行程序设计的能力,它使用了结构程序设计中的Do While运算。原始递归运算不像极小化运算的功能那样强,它也包含循环,但在某些情况下,循环次数是预先确定的,这与使用任意检测在每一步确定终止条件是否满足的情形正好相反。使用Do While和FOR循环均可实现原始递归运算。
结构化程序设计最初由Dijkstra提出,1966年G.Jacopini和C.Bohn从理论上证明了:任何单入口、单出口程序仅使用序列、循环和条件三种结构就可以表示出来。这种程序设计方法采用了反复运用几个简单运算的思想,用这三种结构我们可以很方便完成递归函数理论的基本运算(图4、图5、图6),从而可以表达任意计算过程。
图4 序列运算表达的复合
图5 使用“Do While”的极小化 图6 使用“Do while”(定义一个单自变量函数r(x))的原始递归
在原始递归中如果我们开始就知道执行的次数,则完全可以用for循环来实现。由于全函数经过极小化运算后可能不是全函数,即不存在最小y的解,从而结构程序设计中Do While循环可能出现死循环,这在程序设计中要值得注意。利用结构程序设计语言提供的控制机制,我们可以很容易构造出原始函数和复合、原始递归和极小化运算。下面是用C语言函数实现的三个原始函数和三个运算,利用这六个函数可以计算任何可计算函数,完成递归理论的运算。可见程序设计的能力和递归函数理论表达能力是相同的,函数的构造和程序设计是等价的。
◆ 零函数 ◆原始递归运算
int zero(int x) int recursion(int y)
{ {
return(0); int k,h;
} h=f(x1,…,xn);
◆ 后继函数 while(y<>k)
int successor(int x) {
{ h=g(x1,…,xn,k,h);
return(x+1); k++;
} }
◆ 广义单位函数 return(h);
int projection(int i,int x1,int x2,…,int xn) }
{ ◆极小化运算
if(i==1)return(x1); int minmalisation()
if(i==2)return(x1); {
… int y,k;
if(i==n)return(xn); y=0;
} k=f(x1,…,xn,y);
◆ 复合运算 while(k<>0)
int composition() {
{ y++;
int y1,y2,…,yk; k=f(x1,…,xn,y);
y1=f1(x1,…,xn); }
y2=f1(x1,…,xn); return(y);
… }
yk=f1(x1,…,xn);
return(g(y1,…,yk));
}
程序设计是计算机实践的基本活动,而递归思想直接影响了程序设计的构造,它决定了程序设计语言的许多关键技术,从而递归过程、递归程序就十分自然了。简单地说,递归过程就是自身调用自身过程,包含递归过程的程序我们称为递归程序。在程序设计中使用递归算法往往可以简化求解问题的复杂性。如著名的梵天塔问题,这个问题只有用递归方法解决,而不能用其他方法有效求解。用递归过程描述如下:
void Hanoi(int n,char left,char middle,char right)
{
if(n==1)move(1,one,-,three);
else
{
hanoi(n-1,left,right,middle);
move(1,left,-,right);
hanoi(n-1,middle,left,right);
}
}
在编译技术中递归过程使用更为普遍,处理符号表达式递归过程尤为自然,因为这样的程序结构和数据结构相匹配。下面是Pascal语言一个子集TINY语言的文法(图7),从文法中我们可以看到许多递归结构,所以语法分析采用递归下降文法进行分析自然就很简单。我们为每一文法成分构造一个函数,这些函数之间相互调用,直接或间接就构成了递归。
图7 TINY语言的文法
递归程序中的变量与机器中的存储单元对应,当程序被它本身调用时,它将使用相同的存储单元改写它们原先的内容。所以有了栈这样的数据结构,用来存储必须保存的寄存器内容。这一存储在进入子程序前由调用程序完成或在子程序使用前完成。为了增强递归程序设计的效率,现在的计算机体系结构中设有硬件栈数据结构,它由一组寄存器组成,并且用专用的指令push和pop来处理栈操作。由此可见,递归思想在计算机系统中是非常普遍的,它甚至影响了计算机的体系结构。
递归函数理论作为计算机科学的元科学,对计算机实践具有非常重要的意义,而程序设计作为计算机科学基本的实践活动,递归思想直接影响了程序设计语言的构造,也影响了计算机的体系结构。递归是一种普遍的思维机制,这在计算机科学的理论和实践中得到了很广泛的应用,对计算机的发展起了至关重要的作用。
[参考文献]
1、(美)F.S.Beckman 程序设计的数学基础 1991.8 科学出版社
2、(英)J.M.布雷迪 计算机科学理论-程序设计途径 1988.4 科学出版社
3、董荣胜、古天龙 计算机科学与技术方法论 2002.9 人民邮电出版社
分享到:
相关推荐
许多教科书都把计算机阶乘和菲波那契数列用来说明递归,非常不幸我们可爱的著名的老潭老师的《C语言程序设计》一书中就是从阶乘的计算开始的函数递归。导致读过这本经书的同学们,看到阶乘计算第一个想法就是递归。...
C语言递归函数设计,如何使用递归函数进行算法计算,这样可以提高程序的质量
递归函数的设计关键在于正确地定义基线条件和递归情况,确保递归调用最终能收敛到基线条件。同时,为了避免无限递归,开发者需要确保没有错误地将递归情况误设为基线条件。 总的来说,Delphi的递归函数是一种强大的...
递归函数的结束条件是递归函数设计的关键一步,没有结束条件,递归函数将无法停止,导致程序崩溃。 递归函数的设计需要遵循一定的规则和步骤,否则会导致递归函数的设计失败。递归函数的设计需要考虑问题的规模、...
递归函数和尾递归优化是算法设计中的重要概念,它们在解决某些问题时能够提供直观且优雅的解决方案。在函数式编程语言中,由于递归通常是实现重复运算的唯一方法,因此尾递归优化显得尤为重要。而在像Python这样的...
递归函数和迭代函数是两种不同的程序设计方法。递归函数将问题转化为规模较小的子问题,而迭代函数使用循环来解决问题。 典型案例 本资源提供了两个典型案例: * 案例1:汉诺塔问题,通过递归函数解决汉诺塔问题...
阿克曼函数是一种著名的计算上界递归函数,它在理论计算机科学中有着重要的地位,尤其是在探讨递归和计算复杂性的领域。这个函数是不可计算的,也就是说,它不能通过有限步骤的算法来解决,但是可以通过其他方法如...
总之,迭置法是递归函数论中的基础工具,它允许我们通过已有的简单函数构建复杂的函数结构,这在程序设计、算法设计以及理论计算机科学中都有着广泛的应用。通过深入理解迭置法及其变体,我们可以更好地理解和创造...
在JavaScript中,我们可以定义一个递归函数recursion()来计算第n项的值。函数首先检查输入n的有效性,如n小于0则返回错误信息,n等于0或1则直接返回相应的斐波那契数,否则根据斐波那契数列的定义,通过递归调用...
在实验“实验二 递归下降语法分析程序设计”中,学生将会学习如何设计和实现这样的解析器。实验指导书中会包含具体的步骤、示例代码以及操作流程,以帮助学生理解和实践递归下降分析。 首先,理解递归下降分析的...
《五章节递归函数论》PPT课件主要讲解了递归函数理论中的核心概念——迭置法。迭置法是一种构建新函数的方法,通过已有的函数进行组合形成新的复合函数。这一方法在计算机科学中尤其重要,因为它涉及到函数的组合和...
递归函数:用函数自身给出定义的函数称 为递归函数。 递归关系:对原问题的求解可转化为对其 性质相同 的子问题的求解。 递归方法:用于解决一类满足递归关系的 问题 本资源是递归程序设计详细介绍与实现,简单...
### 递归算法在C/C++程序设计中的描述与实现 #### 1. 引言 递归作为计算机科学中一种强大的问题解决方法,在解决复杂问题时提供了简单且直观的解决方案。递归算法的主要优点包括代码结构清晰、可读性强以及易于...
递归程序设计的基本思想是将问题分解成更小的子问题,然后使用递归函数来解决这些子问题。 递归函数的基本结构 递归函数的基本结构包括两个部分:递归函数的调用和递归函数的出口。在递归函数的调用中,我们需要...
递归下降语法分析程序设计 递归下降语法分析程序设计是编译方法中的一种重要技术,用于对简朴的赋值语句进行语法分析。该程序设计采用递归下降分析程序,通过自上而下的分析方式,来实现对赋值语句的语法分析。 ...
C语言递归函数是程序设计中的一个重要概念,它指的是在函数内部直接或间接地调用自身来解决问题。递归函数的执行过程和求解方法对于初学者来说是难点,但一旦掌握,能够极大提高解决特定类型问题的效率和程序的...
本文对算术表达式文法的递归下降语法分析程序进行了详细的知识点总结,包括算术表达式文法、递归下降语法分析、LL(1)文法、设计原理、实验内容、数据结构设计、递归函数设计、语法分析步骤、测试用例和实现方法等...
### 精通递归程序设计 #### 一、递归程序设计概述 递归是一种在计算机科学中广泛使用的编程技巧,它允许一个函数通过直接或间接的方式调用自身来解决问题。递归不仅可以简化代码,还能使一些复杂问题的解决变得...
在递归下降分析中,EBNF的每个非终结符都对应一个函数,这个函数通过递归调用来解析对应的文法规则。当分析器遇到文法中的非终结符时,会调用相应的函数,函数内部再根据文法规则进行解析。 实验内容涉及的文法E→E...
递归程序设计是一种在计算机科学中广泛使用的编程技术,它基于解决问题的方法自包含地定义自身。这种方法特别适合处理具有重复结构或子问题与原始问题性质相同的问题。在本篇文章中,我们将深入探讨递归程序设计的...