递归算法

 摘要:递归算法,结构清晰,形式简单,符合人的思维习惯,容易被理解和阅读,因而成为计算机程序设计中的一种重要方法,掌握它也有助于理解其他算法。该文阐述了递归算法的基本概念,成立的三个条件,直接和间接递归分类,通过实例深入分析递归在数据结构、函数应用和执行过程中的应用,以及将递归转化为非递归的一般方法。
中国论文网 http://www.xzbu.com/8/view-3705319.htm
  关键词:递归;算法;消除;程序;应用
  中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2012)30-7229-06
  1 递归概念
  1.1 概述
  本文阐述了递归算法的基本定义、成立的必要条件和递归执行的特点以及在实例中的具体应用,让学生能理解“递归是一种思想”这个概念。
  在生活实际中,有些问题是不能用数学公式解决的,需要通过其他方式、其他算法才能完成,其他重要算法有分治法、回朔法和动态规划等。分治法的三个步骤为:①分解:将当前区间一分为二,求分裂点;②求解:递归地对两个子区间进行归并排序;③组合:将已排序的两个子区间归并为一个有序的区间。其递归的终结条件:子区间长度为1(一个记录自然有序)。 回朔法的三个步骤:①搜索策略:符合递归算法,问题解决可以化为子问题,其子问题算法和原问题相同,只是数据增大或减少;②控制策略:避免不必要的穷举搜索,遇到搜索失败,从失败点返回到上一点重新搜索;③数据结构:用数组保存搜索过程中的状态、路径。可见,其他算法依然以递归算法为基础,利用递归帮助解决问题。
  1.2 概念和成立条件
  递归是设计和描述算法的一种有力的工具,它在复杂算法的描述中被经常采用
  1.2.1 概念
  一个函数、过程、概念或数学结构,如果在其定义或说明内部直接地或间接地出现有其本身的引用,或者是为了描述问题的某一状态,必须用到它的上一状态,而描述上一状态,又必须用到它的上一状态………这种用自己定义自己的方法,称之为递归或者是递归定义。
  1.2.2 成立条件
  应满足三点:①符合递归的描述:需要解决的问题可以化为子问题求解,而子问题求解的方法与原问题相同,只是数量增大或减少;②递归调用的次数是有限的;③必须有递归结束的条件。
  1.3 递归分类
  1.3.1 直接递归
  程序设计中,过程或函数直接或者间接调用自己,就被称为递归调用。子程序直接调用自己,这称为直接递归;嵌套关系的子程序A和B,内层的B调用外层的A,这是间接低归;平级关系的子程序A和B,其中A调用了B,B调用了A,这也是间接递归,不过,这种间接递归用到了“超前引用”的规则。
  2 递归本质
  2.1 函数递归调用机制
  递归函数调用同样遵守函数调用机制,当函数调用自己时也要将函数状态、返回地址、函数参数、局部变量压入栈中进行保存。
  实际上函数被调用时执行的代码是函数的一个副本,与调用函数的代码无关。当一个函数被调用两次,则函数就会有两个副本在内存中运行,每个副本都有自己的栈空间且与调用函数的栈空间不同,因此不会相互影响。这种调用机制决定了函数是可以递归调用的。
  2.2 递归调用优缺点
  递归使一些复杂的问题处理起来简单明了,尤其在学习算法设计、数据结构时更能体会到这一点。但是,递归在每一次执行时都要为局部变量、返回地址分配栈空间(对方法的每次递归调用都会生成新的局部变量和局部参数。假如递归层次太多的话,就会消耗太多的stack),这就降低了运行效率,也限制了递归的深度。因此,在必要的时候可以只使用递归的思想来求解,而程序则转用非递归的方式书写。
  3 递归的应用
  3.1 递归定义的数据结构
  3.1.1 二叉树(定义)
  二叉树的递归定义 二叉树或者是一棵空树,或者是一棵由一个根结点和两棵互不相交的左子树和右子树所组成的非空树,左子树和右子树又同样都是二叉树。
  下面介绍二叉树的二叉链式存储结构。我们先给出二叉链表链结点类型描述:
  tnode为链表结点类型名,tlink为指向链结点的指针类型,elemtp为结点数据的类型.
  那么如何根据输入的数据建立二叉链表呢?设二叉树结点数据类型为字符型,各结点数据按照二叉树的数组表示方式存储在字符串str中,字符串变量为s;string、整型变量为n;integer及指针为root;tlink,它们已经在外部说明,则二叉链表的建立过程可表示为procedure build(str;string);其功能为根据字符串str的内容建立二叉树的二叉链表,并让root指向这个二叉链表。其处理过程为:以1为参数调用递归子函数function build0(i;integer):tilink完成二叉链表的建立,并让root指向该链表。递归子函数function build0(i;integer):tilink的功能为:以字符串str的第i个元素为二叉树的根结点递归的建立二叉链表,并返回指向该链表的指针。其处理过程为:
  若i小于字符串的长度,且字符串的第i个元素为非空格符,则创建一个链结点,在其数据域中存放字符串的第i个元素;
  以下是程序清单:
  3.2 递归定义函数
  3.2.1 阶乘
  《例》 用递归计算n!
  3.3 递归定义过程
  3.3.1 树的遍历
  根据二叉树的递归定义,一棵非空二叉树由根结点、左子树和右子树组成,因此遍历一棵非空二叉树的问题可分解为三个问题,即访问根结点、遍历左子树和遍历右子树。显然,遍历左、右子树的问题仍然遍历二叉树的问题,所以二叉树的这三种遍历方式可以用递归算法实现。
  我们以遍历方案DLR(因为访问根结点的操作在遍历左、右子树之前,故称之为前序遍历或先根遍历)为例,若二叉树不为空,则
  访问根结点;
  以前序遍历方式遍历根结点的左子树;   以前序遍历方式遍历根结点的右子树;
  设p为指向二叉树根结点的指针,则前序遍历过程可表示为 procedure preorder0(p:tlink),
  其功能为对p所指的二叉树进行前序遍历,输出前序遍历的结点序列,其处理过程为:
  若p非空,则
  ① 显示p所指的结点数据;
  ② 前序遍历p所指的左子树;
  ③ 前序遍历p所指的右子树;
  以下为程序清单:
  4 递归消除
  为了提高算法的程序运行速度及减少占用内存空间,和透切理解递归递归机制(这种理解是熟练掌握递归程序技能的必要前提),我们接下来探讨递归消除。
  递归消除,就是将一个递归算法转化为等价的非递归算法。递归消除一般有两种方法:
  一、基于循环的递归消除。不是用工作栈作为工作机制,而是利用循环算法,即采用递推算法,这样可避免重复计算,提高了效率,如下面所要讲的斐波那契数列。
  二、基于栈的递归消除。大部分递归问题无法用递推算法来消除,在这种情况下,引用一个工作栈作为控制机构以消除递归算法,其原理是:利用数组模拟工作栈,保存“返回位置”,以实现过程调用和返回控制。
  4.1 利用栈消除递归
  我们以Hanoi(河内/汉诺)塔问题为例,看如何利用数组建立的栈来消除递归的。
  例: Hanoi(河内/汉诺)塔问题
  有n个圆盘,依半径大小(半径都不同),自下而上套在A柱上,每次只允许移动最上面的一个盘子到另外的柱子上去(除A柱子外,还有B柱子和C柱子,开始时这两个柱子上没盘子),但绝不允许发生柱子上出现大盘子在上,小盘子在下的情况,现在要求设计将A柱子上n个盘子搬到C柱子上去的方法。
  问题解析:本题是典型的递归程序设计题。
  3) 当n=3时,需要将前2个盘子移到B柱子,再将第三个盘子移到C柱子,然后将2个在B柱子上的盘子借助A柱子移动到C柱子,因此可以得到移动盘子的一般规律:
  a.先将n-1个盘子从A 柱子移动到B柱子,C柱子为中间柱子;
  b.将第n个盘子从A柱子移动到C柱子;
  c.再将n-1个盘子从B柱子移动到C柱子,A柱子为中间柱子。
  其程序如下:
  为了保证递归调用正确执行,系统要建立一个递归调用工作栈,为各层次的调用分配数据存储区。每一层递归调用所需要的信息构成一个工作记录,其中包括所有实参指针,所有局部变量以及返回上一层的地址。每进入一层递归调用,就产生一个新的工作记录压入栈顶。每退出一层递归调用,就从栈顶弹出一个工作记录。
  4.2 利用循环消除递归
  例:用递归的方法求斐波那契数列中的第n个数
  程序清单如下:
  这样,就可以将递归程序转化为非递归的程序了。
  斐波那契数列用非递归算法求解的程序如下:
  5 总结
  总的说来,递归是一种非常重要的,应用很广泛的程序设计方法。递归的能力在于用有限的语句来定义对象的无限集合。用递归思想写出的程序往往十分
  简洁易懂,结构清晰,形式简单,符合人们的日常思维习惯,容易被理解和阅读。其他算法,如分治法,有许多是源于递归思想,或是由递归分解+合并处理,还有如回朔法和动态规划问题 ,动态规划的子问题重叠性质与递归有某种相似之处,递归+动态修改查表是一种不错的建立动态规划模型的方法。可见,掌握递归算法、理解递归思想对于学习其他程序设计方法也是很有帮助的。
  递归使一些复杂的问题处理起来简单明了,尤其在学习算法设计、数据结构时更能体会到这一点。但是,递归在每一次执行时都要为局部变量、返回地址分配栈空间,假如递归层次太多的话,就会消耗太多的stack,对内存要求很高,这就降低了程序运行效率,也限制了递归的层次和深度。因此,在必要的时候可以只使用递归的思想来求解,而程序则转用非递归的方式书写。
  参考文献:
  [1] 吴再陵,高建军.全国青少年信息学培训教材[M].南京: 南京大学出版社,2002.
  [2] 朱振元,朱承.数据结构教程--面向对象实现方法[M].西安:西安电子科技大学出版社,2000.
  [3] 邓毅.Delphi 4.0入门与提高[M].北京:清华大学出版社,1999.
  [4] 严蔚敏.数据结构[M].北京:清华大学出版社,1992.
  [5] 李大友.数据结构与算法[M].北京:机械工业出版社,1996.
  [6] 旺晓东.计算机算法设计与分析[M].北京:电子工业出版社,2004.

posted on 2014-01-14 18:20  yun_  阅读(9707)  评论(0编辑  收藏  举报