算法设计与分析:递归和分治(Python)

实验目的和要求:

1.递归:掌握递归算法的两个基本组成、编程实现、时间分析;
使用turtle模块实现递归可视化。
2.分治:掌握分治法的设计思想、求解步骤、掌握用分治法解题的算法框架。

实验内容和原理:

1.递归:分形树(自相似递归图形)

问题描述:
分形是在不同尺度上都具有相似性的事物,树的树枝形状也具有分形的特点,我们能看出,一棵树的每个分叉和每条树枝,实际上都具有整棵树的外形特征。这样我们可以把树分解成三个部分:树干、左边的树枝、右边的树枝。这样的分解正符合递归的定义:对自身的调用。

编程任务:
用turtle模块+递归算法,设计自己的分形树

2.分治:Gray码问题

问题描述
Gray码是一个长度为2n的序列。序列中无相同的元素,每个元素都是长度为n位的串,相邻元素恰好只有一位不同。用分治策略设计一个算法对任意的n构造相应的Gray码。

编程任务
利用分治策略试设计一个算法对任意的n构造相应的Gray码。
数据输入
从键盘输入或程序自动产生随机数作为输入数据n。
结果输出
程序运行结束时,将得到的所有Gray码输出到屏幕

源程序:

1.分形树:

import turtle as tt
import random
#花朵
def point(n,m,s1,s2):#在当前位置和当前位置附近画点,m:附近距离、s1,s2:点的颜色——组合成一朵花
    tt.dot(n, s1)#n:点的直径,s1:点的颜色
    tt.penup()
    tt.backward(m)#另一个位置画点
    tt.pendown()
    tt.dot(n//2, s2)#直径和颜色不一样
    tt.penup()
    tt.forward(m)#回到原来的位置
    tt.pendown()
def branch(l):#产生4枝树枝
    a=random.randint(0,l/2)#树枝长度随机
    tt.forward(a)#随机长度枝干
    tt.dot(8,"lightcoral")#树枝上画一个有颜色的点
    tt.backward(a)#回到原来位置
    #重复
    b=random.randint(0,l/2)
    tt.right(20)
    tt.forward(b)
    tt.dot(8, "lightcoral")
    tt.backward(b)
    tt.left(40)
    c=random.randint(0,l/2)
    tt.forward(c)
    tt.dot(8, "lightcoral")
    tt.penup()
    tt.backward(c)
    tt.right(20)
    tt.pendown()
def tree(l,ps):
    if l<=5:
        # tt.froward(l)
        point(17,3,"lightcoral","RosyBrown2")#画树枝上的花花
        return

    else:
        if l <=150:
            point(10,3, "sky blue", "RosyBrown2")
            branch(l)

        tt.color("LightSalmon4")
        tt.pensize(ps)
        tt.forward(l)
        tt.right(20)#顺时针20度角
        tree(l-30,ps*0.8)#子枝干的粗细是母枝的0.8,长度比母枝少30
        tt.left(40)#逆时针40度角
        tree(l-30,ps*0.8)
        tt.right(20)
        tt.backward(l)#回到枝干起始位置

tt.bgcolor(0.5,0.5,0.5)#设置黑色背景色
tt.penup()
tt.goto(0,-400)#起点位置
tt.speed(10)#画笔速度
tt.pendown()
tt.left(90)#设置画笔方向竖直
tree(200,5)#主干长度为200,主干粗细参数为5
# tt.hideturtle()
tt.done()

先画“树干”,每次画“树枝”时递归调用自身,并使规模减小,最后达到画树的结果。
在这里插入图片描述
2.Gray码:

# 构造w位格雷码,n为格雷码的个数
def gray(w,n):
# 如果格雷码宽度为1
    if w == 1:
            arr[0][0] = 0
            arr[1][0] = 1
            return

    # 格雷码最高位
    for i in range(int(n / 2)):
            # 生成的格雷码前一半最高位填“0”
            arr[i][int(w - 1)] = 0
            # 后一半最高位位填“1”
            arr[int(n / 2 + i)][int(w - 1)] = 1

# Output(arr)
    gray(w - 1, int(n / 2))

# 生成w - 1位格雷码,填写到目标码高半部分
    n1 = int(n / 2)
# print(n1)
    for i in range(n1,n):  # 填入格雷码低半部分
        for j in range(w - 1):
            arr[i][j] = arr[n - i - 1][j]

# 主函数
width = int(input("输入Gray码的宽度:"))
num = 2 ** width
arr = [[None for i in range(width)] for i in range(num)]  # 定义Gray码的存储结构
# arr1=[]
# for k in range(0,width):
#     arr1.append(0)
# arr=[]
# for k in range(0,num):
#     arr.append(arr1)
gray(width,num)
for i in range(int(len(arr))):
    # s=(str)(arr[i])
    print(arr[i])

在这里插入图片描述

先将码分为上下两段,上段为上次递归结果,下段为上段的翻转,然后上段和下端处理后合并为最终结果

讨论、心得:

  1. 使用递归时可以简化算法思路,有时也能减小算法的时间复杂度。
  2. Turtle可以实现画图,用递归来减小问题规模,最终实现画树。
    3.分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,如果子问题的答案都求出来了,就可以求出原问题的答案。
    4.(n+1)位格雷码中的前个码字等于n位格雷码的码字,按顺序书写,加前缀0;
    (n+1)位格雷码中的后个码字等于n位格雷码的码字,按逆序书写,加前缀1;
    (n+1)位格雷码的集合=n位格雷码集合(顺序)加前缀0+n位格雷码集合(逆序)加前缀1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@小冯@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值