数据结构与算法Python版 递归与可视化

Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本


一、递归

递归Recursion是一种解决问题的方法

  • 将问题分解为规模更小的相同问题,持续分解,直到问题规模小到可以用非常简单直接的方式来解决。
  • 递归的问题分解方式非常独特,其算法方面的明显特征就是:在算法流程中调用自身
  • 递归为我们提供了一种对复杂问题的优雅解决方案,精妙的递归算法常会出奇简单。

重要:递归“三定律”

  • 递归算法必须有一个基本结束条件(最小规模问题的直接解决)
  • 递归算法必须能改变状态向基本结束条件演进(减小问题规模)
  • 递归算法必须调用自身(解决减小了规模的相同问题)

示例:使用递归对数列进行求和

  • 数列的和=“首个数”+“余下数列”的和
  • 如果数列包含的数少到只有1个的话,它的和就是这个数了。这是规模小到可以做最简单的处理
    • 问题分解为更小规模的相同问题,并表现为“调用自身
    • 对“最小规模”问题的解决:简单直接
      在这里插入图片描述
def list_sum(num_list):
    if len(num_list) == 1:  # 基本结束条件
        return num_list[0]
    else:
        # 减少规模,向长度为1的状态演进,并调用自身
        return num_list[0] + list_sum(num_list[1:])  


list1 = [1, 3, 5, 7, 9]
print(list_sum(list1))


### 输出结果
25

二、递归实现分析

当一个函数被调用的时候,系统会把调用时的现场数据压入到系统调用栈

  • 每次调用,压入栈的现场数据称为栈帧
  • 当函数返回时,要从调用栈的栈顶取得返回地址,恢复现场,弹出栈帧,按地址返回。
    在这里插入图片描述

Python中的递归深度限制

  • Python中的递归深度限制,默认最大递归深度为1000。超过最大递归深度会出现RecursionError错误。
  • 这时候要检查程序中是否忘记设置基本结束条件,导致无限递归。
import sys

print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())


### 输出结果
1000
2000

三、递归可视化-分形树

Python内置turtle海龟绘图模块模拟海龟在沙滩上爬行而留下的足迹

动作类别方法名参数说明
爬行forward(n)n向前爬行n个单位长度
爬行backward(n)n向后爬行n个单位长度
转向left(a)a向左转动a度
转向right(a)a向右转动a度
抬笔放笔penup()抬起画笔,移动时不画线
抬笔放笔pendown()放下画笔,移动时开始画线
笔属性pensize(s)s设置画笔线条的粗细为s
笔属性pencolor©c设置画笔的颜色为c

示例:画正方形

import turtle

t = turtle.Turtle()
for i in range(4):
    t.forward(100)
    t.right(90)
turtle.done()

示例:画五角星

import turtle

t = turtle.Turtle()
t.pencolor("red")
t.pensize(3)
for i in range(5):
    t.forward(200)
    t.right(144)
turtle.done()

示例:递归画螺旋

from turtle import Turtle
import turtle

t = turtle.Turtle()

def draw_spiral(t: Turtle, line):
    if line > 0:
        t.forward(line)
        t.right(90)
        draw_spiral(t, line - 5)


draw_spiral(t, 100)
turtle.done()

在这里插入图片描述

分形树:自相似递归图形

  • 分形Fractal,是1975年由Mandelbrot开创的新学科。“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。
  • 分形是在不同尺度上都具有相似性的事物。我们能看出一棵树的每个分叉和每条树枝,实际上都具有整棵树的外形特征(也是逐步分叉的)
  • 我们可以把树分解为三个部分:树干、左边的小树、右边的小树。分解后,正好符合递归的定义:对自身的调用
    在这里插入图片描述
from turtle import Turtle
import turtle

t = turtle.Turtle()
t.left(90)
t.pencolor("green")

def draw_tree(t: Turtle, line):
    if line > 0:  # 递归结束条件
        t.forward(line)  # 画树干
        t.right(30)  # 右倾30度
        draw_tree(t, line - 15)  # 递归调用,画右边小树
        t.left(60)  # 向左回60度,即左倾30度
        draw_tree(t, line - 15)  # 递归调用,画左边小树
        t.right(30)  # 向右回30度,即回正
        t.backward(line)  # 退回原位置

draw_tree(t, 100)
turtle.done()

在这里插入图片描述

四、递归可视化-谢尔宾斯基三角形

谢尔宾斯基Sierpinski三角形

  • 分形构造,平面称谢尔宾斯基三角形,立体称谢尔宾斯基金字塔
  • 真正的谢尔宾斯基三角形是完全不可见的,其面积为0,但周长无穷,是介于一维和二维之间的分数维(约1.585维)构造
  • 根据自相似特性,谢尔宾斯基三角形是由3个尺寸减半的谢尔宾斯基三角形按照品字形拼叠而成

算法分析

  • 在degree有限的情况下,degree=n的三角形,是由3个degree=n-1的三角形按照品字形拼叠而成
  • 同时,这3个degree=n-1的三角形边长均为degree=n的三角形的一半(规模减小)
  • 当degree=0,则就是一个等边三角形,这是递归基本结束条件
    在这里插入图片描述
import turtle


def draw_triangle(t: turtle.Turtle, points: dict, color: str):
    # 绘制等边三角形
    t.fillcolor(color)
    t.penup()
    t.goto(points["top"])
    t.pendown()
    t.begin_fill()
    t.goto(points["left"])
    t.goto(points["right"])
    t.goto(points["top"])
    t.end_fill()


def get_mid(p1, p2):
    # 取两点的中点
    return (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2


def draw_sierpinski(degree, points):
    # 递归画谢尔宾斯基三角形
    color = "black" if degree % 2 != 0 else "white"
    draw_triangle(t, points, color)
    if degree > 0:  # 最小规模,0直接退出
        # 左三角形
        draw_sierpinski(
            degree - 1,
            {
                "left": points["left"],
                "top": get_mid(points["left"], points["top"]),
                "right": get_mid(points["left"], points["right"]),
            },
        )
        # 上三角形
        draw_sierpinski(
            degree - 1,
            {
                "left": get_mid(points["left"], points["top"]),
                "top": points["top"],
                "right": get_mid(points["top"], points["right"]),
            },
        )
        # 右三角形
        draw_sierpinski(
            degree - 1,
            {
                "left": get_mid(points["left"], points["right"]),
                "top": get_mid(points["right"], points["top"]),
                "right": points["right"],
            },
        )


t = turtle.Turtle()
points = {"top": (0, 200), "left": (-200, -100), "right": (200, -100)}
draw_sierpinski(degree=3, points=points)
turtle.done()

当degree为3时的三角形
在这里插入图片描述


您正在阅读的是《数据结构与算法Python版》专栏!关注不迷路~

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值