数据结构与算法分析(四):递归

本文介绍了Python中的递归算法,包括递归的基本原则,如基本情况、状态改变和递归调用。通过递归实现了计算数列之和、整数转任意进制字符串,并详细讲解了谢尔平斯基三角形的绘制。递归的思想在编程中用于解决复杂问题,通过不断分解子问题达到求解目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本系列为《Python数据结构与算法分析》第二版学习笔记,作者:布拉德利.米勒;戴维.拉努姆。


递归是解决问题的一种方法,它将问题不断地分成更小的问题,直到子问题可以用普通的方法解决。通常情况下,递归会使用一个不停调用自己的函数。

一、递归三原则

(1)递归算法必须有基本情况;
(2)递归算法必须改变其状态并向基本情况靠近;
(3)递归算法必须递归的调用自己。

基本情况是指使算法停止递归的条件,这通常是小到足以直接解决的问题。为了遵守第二条原则,必须设法改变算法的状态,从而使其向基本情况靠近。改变状态是指修改算法所用的某些数据,这通常意味着代表问题的数据以某种方式变得更小。最后一条原则是递归算法必须对自身进行调用,这正是递归的定以。递归的逻辑并不是循环,而是将问题分解成更小、更容易解决的子问题。

二、用递归计算一列数之和

假设需要计算数字列表[1, 3, 5, 7, 9]的和,一般用循环求和可以解决。

def listsum(numList):
	theSum = 0
	for i in numList:
		theSum += i
	return theSum

如何利用递归解决这个问题,数字列表numList的总和等于列表中的第一个元素(numList[0])加上其余元素(numList[1:])之和,可以用函数的形式来表述这个定以:
listSum(numList) = first(numList) + listSum(rest(numList))
first(numList)返回列表中的第一个元素,rest(numList)则返回其余元素,代码实现如下:

def listsum(numList):
	if len(numList) == 1:
		return numList[0]
	else:
		return numList[0] + listsum(numList[1:])

这里,第2行检查列表是否只包含一个元素,这个检查很重要,同时也是该函数的退出语句,满足原则1。对于长度为1的列表,其元素之和就是列表中的数。其次,listsum函数在第5行调用了自己,这就是将listsum称为递归函数的原因。

三、将整数转换为任意进制的字符串

前面我们用while循环解决过这个问题,这里我们用递归来处理。
以十进制整数769为例,假设有一个字符序列对应前10个数,比如convString = “0123456789”。若将一个小于10的数字转换成其对应的字符串,只需在字符序列中查找对应的数字即可。上述算法情况说明,整个算法包含三个组成部分:
(1)将原来的整数分成一系列仅有单数位的数;
(2)通过查表将单数位的数转换成字符串;
(3)连接得到的字符串,从而形成结果。

rStack = Stack()

def toStr(n, base):
	convertString = "0123456789ABCDEF"
	if n < base:
		rStack.push(convertString[n])
	else:
		rStack.push(convertString[n % base])
		toStr(n // base, base)

四、用递归画谢尔平斯基三角形

手动绘制谢尔平斯基三角形过程如下:从一个大三角形开始,通过连接每条边的中点将它分割成四个新的三角形;然后忽略中间的三角形,利用同样的方法分隔其余三个三角形。
在这里插入图片描述
代码如下:

class SierPinski():
    def __init__(self):
        pass

    def drawTriangle(self, points, color, myTurtle):
        myTurtle.fillcolor(color)
        myTurtle.up()
        myTurtle.goto(points[0])
        myTurtle.down()
        myTurtle.begin_fill()
        myTurtle.goto(points[1])
        myTurtle.goto(points[2])
        myTurtle.goto(points[0])
        myTurtle.end_fill()

    def getMid(self, p1, p2):
        return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2)

    def sierpinski(self, points, degree, myTurtle):
        colormap = ['blue', 'red', 'green', 'white', 'yellow', 'violet', 'orange']
        self.drawTriangle(points, colormap[degree], myTurtle)
        if degree > 0:
            self.sierpinski([points[0],
                             self.getMid(points[0], points[1]),
                             self.getMid(points[0], points[2])],
                            degree-1, myTurtle)
            self.sierpinski([points[1],
                             self.getMid(points[0], points[1]),
                             self.getMid(points[1], points[2])],
                            degree - 1, myTurtle)
            self.sierpinski([points[2],
                             self.getMid(points[2], points[1]),
                             self.getMid(points[0], points[2])],
                            degree - 1, myTurtle)

if __name__ == '__main__':
    SierPinski = SierPinski()
    myTurtle = Turtle()
    myWin = myTurtle.getscreen()
    myPoints = [(-500, -250), (0, 400), (500, -250)]
    SierPinski.sierpinski(myPoints, 4, myTurtle)
    myWin.exitonclick()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值