2024年5月21日发(作者:)
科技信息 专题论述
递归算法硇研夯及经典算法硇递归实坝
常州工学院计算机信息工程学院 丁志云
[摘要]递归思想是计算机科学的一个重要思想,递归方法是程序设计中的有效方法,它为程序设计者打开了一个全新的程序设计
思路。采用递归思想编程,可以将一些貌似复杂的问题简单化,编写的程序更加简洁明了。本文深入分析了递归思想的特点,递归算
法的优点和缺点,通过对多个经典算法的递归实现,让读者掌握递归算法程序设计的一些方法和技巧,有助于提高程序初学者的编
程水平。
[关键词]递归 算法
1.引言
程序设计
阶段,层层返回最终得到问题的解答。如图2所示是递归算法执行过程
示意图。
5.递归算法实例
递归算法是一种直接或者间接地调用自身的算法。在计算机程序
设计中,递归算法对解决有些问题是十分有效的,它往往使算法的描述
简洁而且易于理解,当使用非递归方法难于解决问题时,尝试用递归方
法也许会给你带来意想不到的惊喜。著名的汉诺塔(Hanoi)问题,八皇
后问题,斐波那契(Fibonacci)的兔子问题,猴子吃桃问题,年龄问题等
都是递归问题。
2.递归算法的特点
递归就是在过程或函数里调用自身。递归程序在执行过程中总是
不断地调用自身,而每次调用自身时,通常在规模上都有所缩小,当问
题的规模缩小到某一值时就可以直接给出解答而不再进行递归调用,
因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条
件),而且相邻两次调用之间有紧密的联系,前一次要为后一次做准备
(通常前一次的输出就作为后一次的输入),在使用递归策略时,必须有
一
个明确的递归结束条件,也称为递归出口。
递归算法一般用于解决三类问题:
(1)数据的定义是按递归定义的,如Fibonacci函数。
(2)问题解法按递归算法实现,如回溯问题。
(3)数据的结构形式是按递归定义的,如树的遍历,图的搜索等。
递归算法设计的基本思想是:对于一个复杂的问题,把原问题分解
为若干个相对简单的同类子问题,继续下去直到子问题简单到能够直
接求解,也就是说到了递归的出口,这样原问题就有递推得解。所以在
使用递归算法时,首先要弄清楚简单情况下的解法,然后弄清楚如何把
复杂情况归纳为更简单的情况。
3.递归算法的分类
递归算法一般通过函数或子过程来实现。在函数或子过程的内部,
直接或者间接地调用自己的算法。所以根据递归算法的表示形式,可以
将递归算法分为递归函数和递归子过程两种;根据递归算法调用的形
式可以有直接递归和间接递归两种。如图1所示是直接递归和间接递
归调用过程的示意图。
旨 当闻{ 小
捌薹一
递归函数
或子过程 问颓匍
J、
A ]
l1. ̄iitB间I蠹递归
图l直接递归和间接递归调用过程的示意图
4.递归算法的执行过程
开始递归过程A 递归过程A 递归过程A递归过程A
苦
静
结柬 调用A—
:
I
调用A一
r 静管
图2递归算法执行过程示意图
递归算法求解问题是通过不断调用自身来实现的,在反复调用过
程中,通常将问题的规模不断缩小,当缩小到某一值时,就能够直接求
解,再一一返回后求出问题的最终解。所以递归算法的执行分为两个阶
段,第一阶段是逐层调用阶段,又称为递推阶段。在这一阶段通常是对
一
个规模较大问题的求解转化成一个规模较小问题的求解,当规模小
到某一值时,就能直接得到问题的解答,而不必再递归调用。第二阶段
是逐层返回阶段,又称为回归阶段。当第一阶段完成后,进入逐层返回
编写递归程序从两个方面人手,一是找出递归表达式(递归公式),
二是确定递归的终止条件(递归出口),多数递归都有明确的递归表达
式,此类递归算法简单明了,在编写此类递归程序时,通常只用简单的
分支结构就可以实现。例如,求自然数n的阶乘,求斐波那契(Fibon 一
ci)数列的第n项的值,求1-n个连续自然数的和等。下面用VB将我们
教学中常见的经典算法用递归算法来实现。
【例1】用递归算法求自然数n的阶乘。
分析:要求n的阶乘,只要求出n一1的阶乘,则n!=n (n一1)!,可以定
义一个函数fact(n),表示求n!,则递归表达式为:fact(n)=n*fact(n一1),递归
的终止条件是当n=l或者n=0时,fact(n)=1。递归函数如下:
Private Function fact(ByVal a As Integer)As Long
・求n的阶乘
If n:l Orn=0Then
fact=1
Else
fact=n fact(n一11
EndIf
End Function
【例2】用递归算法求斐波那契(Fibonacci)数列第n项的值。
分析:根据Fibonacci数列的特点,可以定义一个函数fib(n),表示求
Fibonacci数列第n项的值,则递归表达式为:ifb(n)=fib(n一1)+fib(n一2),递
归的终止条件是当n=l或者n=2时,fib(n)=l。递归函数如下:
Private Function ifb(ByVal n As Integer)As Integer
’求Fibonacci数列第n项的值
Ifn=1 Orn=2Then
ifb=1
Else
ifb=fib(n一11+fib n一2、
EndIf
【例3】用递归算法求1~n个连续自然数的和。
分析:可以定义一个函数sum(n),表示求l ̄n个连续自然数的和,
则递归表达式为:sum(n)=n+sum(n—1),递归的终止条件是当n=l时,sum
(n)=l。递归函数如下:
Private Function sum(ByVal n As Integer)As Integer
’求1~n个连续自然数的和
Tfn=1 Th n
sum=1
Else
sum n+sum(n一11
EndIf
End Function
【例4】用递归算法实现字符串的反序。
分析:要对一个由n个字符组成的字符串反序,只要对该字符串前
面的n一1个字符实现反序,就可以很容易实现该字符串的反序。可以定
义一个函数reverse(st),表示对字符串st实现反序,则递归表达式为:re—
verse(st)=Right(st,1)&reverse(Left(st,Len(st)一1)),递归的终止条件是当
Len(st)≤1时,reverse(s0=st。递归函数如下:
Private Function reverse(st As Stirng)As Stirng
’字符串反序
IfLen(st)<=1 Then
reverse=st
Else
reverse=Right(st,1)&reverse(Left(st,Len(st)一1))
---——
387---——
科技信息 专题论述
EndIt
End Function
【例5】用递归算法实现将一个十进制整数转换成二进制。
分析:可以定义一个递归函数trans(n),表示将一个十进制整数n转
换成二进制,不难得出它的递归表达式为:trans(n)=trans(n\2)&(n Mod
21,当n=l或者n=O时,trans(n)=n,递归函数如下:
Private Function trans(ByVal n As Integer)As String
’将一个十进制整数转换成二进制
Ifn<:l Then
trans=n
Else
trans:trans(n\2)&(nMod 2)
EndIf
End Function
【例6】用递归算法实现求数组元素之和。
分析:可以定义一个递归函数sum(a0,n),表示求数组a中前n个元
素的和,则递归表达式为:sum(a0,n)=sum(a0,n一1)+a(n),当n=l时,sum(a
0,1)=a(1),递归函数如下:
Private Function sum(a0 As Integer,ByVal n As Integer)As Integer
’求数组前n个元素之和
Ifn=1 Then
sum=a(1)
Else
sum=su,n(a,n—1)+a(n)
EndIf
End unction
【例7】用递归算法求数组中所有数的最大值。
分析:要求出数组中所有数的最大值,若能求出前n一1个数的最大
值(假设数组中共有n个数),则再与第n个数比较,即可得到最大值,
同样的要求出前n一1个数的最大值,则只要求出前n一2个数的最大值,
再与第n一1个数比较,如此下去,当n=l时,最大值就是本身,递归结
束。 。
可以定义一个递归函数max(a0,n),表示求数组a中前n个数的最
大值,则max(a0,n)=max(a0,n—1)与a(n)的比较,若a(n)>max(a0,n一1),则
max=a(n),否则max=max(a0,n一1),递归函数如下:
Private Function Max(a0 As Integer,ByVal n As Integer)As Integer
’求数组前n个元素的最大值
Ifn:1下hPn
Max=af11
Else
Max=MtLx(a,n~l1
Ifa(n1>MaxThenMax=a(n1
EndIf
End Function
【例8】用递归算法判断一个数是否是回文数。
分析:要判断一个数是否是回文数,只要判断首尾数字字符是否相
等,若不等,则不是回文数,若相等,则去掉该数的首尾数字字符,再判
断去掉首尾字符后的新数字是否是回文数,如此下去,当新数字的长度
小于等于1时,是回文数(已知)。递归函数如下:
Private Function hws(ByVal st As Stirng)As Boolean
’判断一个数是否是回文数
IfLen(st1<:1 Then
hws=True
Exit Function
Elself Left(st,1)<>Right(st,1)Then
Exit Function
EndIf
hws=hws(Mid(st,2,Len(st)一2))
End Function
【例9】用递归算法求一个正整数的所有因子,并存放在一个数组
中。
分析:可以定义一个递归子过程gen(n,nl,aO),功能是判断In是否是
正整数n的一个因子,若是则将In存放在数组中,m从1开始,当m>n
时,递归结束,否则m+l,再调用该递归子过程。递归子过程如下:
Private Sub gen(ByVal n As Integer,m As Integer,a0 As Integer)
’求一个正整数的所有因子,存放在一个数组中
Static k As Integer
IfnModm=0ThPn
388...——
k=k+l
ReDim Preserve a(k)
a(k)=m
EndIf
Ifm>nThen
Exit Sub
Else
Call gen(n,m+1,a)
EndIf
End Sub
【例10】用递归算法实现数组的从大到小排序。
分析:要对数组a中所有元素进行排序,若能对前n一1个元素进行
排序(假设数组a中共有n个元素),则在排序好的n一1个元素中找到
插人位置,再将a(n)插入到该位置即可,同样的要对数组a中n一1个元
素进行排序,则先排序好n一2个元素,如此下去,当n=1时,递归结束。
可以定义一个递归子过程sort(aO,n),功能是实现数组a中前n个元素
排序。递归子过程如下:
Private Sub sort(a0 As Integer,n As Integer)
对数组前n个元素进行排序
Dim i As Integer,pos As Integer
Dim temp As Integer
Ifn>1 Then
Call sort(a,n一1)
Fori=1 Ton一1’找插入位置
Ifa(n1>=a(i1 Then
Exit For
EndIf
Next
pos 1
temp a(n1
Fori=n一1 Topos Step一1’循环移位
a“+1):a(i1
Nexti
a(pos1=temp
EndIf
End Sub
【例1 1】用递归算法实现判断一个正整数n是否是素数。
分析:可以定义一个递归函数prime(n,m),功能是判断m是否能被
正整数n整除,若能则该正整数n不是素数,m从2开始,当m=n时,递
归结束,否则m+l,再调用该递归函数。递归甬数如下:
Private Function prime(ByVal n As Integer,m As Integer)As Boolean
’判断一个正整数n是否是素数
Ifm=nThen
prime=True
ElseIfn<2OrnModin=0Then
prime=False
Else
prime=prime(n,m+I)
EndIf
End Function
6.小结
递归算法不仅仅可以用于求解递归描述的问题,在其它很多问题
中也可以用到递归思想,如回溯法、分治法、动态规划法等算法中都可
以使用递归思想来实现,递归的思维与人们的常规思维是相逆的
用递归算法编写的程序虽然简洁明_『,但递归算法解题的运行效
率较低。在递归调用的过程中系统为每一层的返回点、局部量等开辟了
栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算
法设计程序。例如以上介绍的求斐波那契(Fibonacci)数列第n项值的
递归过程,调用一次要产生两个新的调用,递归次数呈指数增长,时间
复杂度为O(2n),若用非递归法求解,它的时间复杂度为O(n)。
参考文献
[1]钟秀玉,陈月峰.基于递归与多线程的丢失文件查找设计[J].计
算机技术与发展,2010.
[2]苗英恺递归程序的教学探讨[I]电脑知识与技术,2008.
[3]符策锐基于vB的递归模拟演示程序的实现[J].电脑开发与应
用、2008
发布者:admin,转转请注明出处:http://www.yc00.com/news/1716299163a2727175.html
评论列表(0条)