#edu019. 第 5 节 递归迭代绘图
第 5 节 递归迭代绘图
在前面的例子中“绘制 个正 边形”,如果有一个代码模块能够帮助我们绘制一个正 边形,那么“绘制 个正 边形”的代码会很简洁,这个代码模块就是函数,一些常用的功能,前人已经编写了函数并封装到不同的库中(头文件),如果用户想自己做一个自己需要的函数,那可以自己定义函数,然后再调用。
定义函数基本格式如下:
函数返回值类型 函数名([形式参数列表])
{
功能语句;
...
[return 返回值]
}
注意:定义函数必须放到主函数外面,上述定义函数框架中 [...]为可以选项。
以“绘制 个正 边形”为例,利用自定义函数,参考代码如下:
void draw(int m) //定义一个函数,函数名draw ,绘制一个正m边形
{
for(int i=1;i<=m;i++)
pen.fd(1000.0/m).rt(360.0/m);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
draw(n); //调用函数,draw为自定义函数,功能是绘制一个正n边形
pen.rt(360.0/n);
}
return 0;
}
程序运行时,每次调用 函数,会将实参 单向复制给形参 ,自定义的函数 ,就负责绘制一个正 边形,从而使得代码逻辑更加清晰,大型程序要实现多种功能,都会将复杂任务分解成很多小任务,然后交给不同函数执行,便于维护,关于详细函数使用细节可以查看后面系统对应章节。
主函数可以调用子函数,子函数之间也可以相互调用,当一个子函数直接或间接调用自己,这就是递归,也被叫做迭代。如果一个问题可以分解成一个或多个子问题,子问题又与原问题具有相似的结构,那就可以用递归来处理(自己调用自己),当然不能无限递归下去,到达一定程度需要返回,否则时间和空间都可能爆炸(递归使用栈空间,每递归一层,就会扩大一层的空间)。
自然界会发现大量整体与部分具有相似性的形态,例如雪花、树冠、花菜、大脑皮层、粒子的布朗运动等,数学上称之为分形,是非线性科学前言和重要分支。瑞典数学家柯赫构造的 “Koch曲线”、波兰数学家提出的“谢尔宾斯基三角形”都是典型的分形图,分形图由于整体与部分具有相似性,这与递归在本质上是相通的,那么就可以利用递归绘制出各种分形图来。
瑞典数学家海里格·冯·科赫在 1904 构造的 “Koch曲线”,也叫雪花曲线。三次 Koch 曲线的构造过程主要分为三大步骤:
第 步:绘制一条线段;第 步:将这条线段中间的 处向外折起(内角为 度);第 步:按照第 步的方法不断的把各段线段中间的 处向外折起。这样无限的进行下去,最终即可构造出 Koch 曲线。下图就是迭代了 次得到的“ Koch 曲线”:

迭代 4 次“Koch曲线”
三角形三边按照上述方法迭代下去,就构成了"科赫雪花",Koch 曲线长度是无限的,"科赫雪花"面积有限,这就得到了数学上的一个悖论:"无穷大"的边界,包围着有限的面积。
例1:请利用计算机绘制"科赫雪花"。
分析:"科赫雪花"是由一个三角形构成,各边是 Koch 曲线,Koch 曲线可以用用递归生成,当长度小于 ,返回。
void draw(double length) //绘制Koch曲线
{
if(length<5)
{
pen.fd(length);
return;
}
draw(length/3);
pen.lt(60);
draw(length/3);
pen.rt(120);
draw(length/3);
pen.lt(60);
draw(length/3);
}
int main()
{
pen.move(-100,-100);
pen.rt(30);
for(int i=1;i<=3;i++) //绘制三角形
{
draw(300); //三角形各边为Koch曲线
pen.rt(120);
}
return 0;
}
可以得到科赫雪花图像如下:

科赫雪花图像
例2:绘制“谢尔宾斯基三角形” 分形
谢尔宾斯基三角形(英语:Sierpinski triangle)是一种分形,由波兰数学家谢尔宾斯基在 1915 年提出。其构造方法比较多,其中一种构造过程如下:
第 步.取一个三角形,使用等边三角形;第 步沿三边中点的连线,将它分成四个小三角形。第 步.去掉中间的那一个小三角形。
对其余三个小三角形重复上述 个过程,如下图:

谢尔宾斯基三角形
分析:观察上图中前两步,找到一种简单的规律,先绘制一个小三角形(边长为大三角形边长的一半),画笔必然回到原位置,让画笔往前移动(大三角形边长),然后画笔再向右旋转 120 度,后面都是重复这个过程,重复 次,采用递归绘制每一个小三角形,当边长小于一定值(再绘制也看不到细节了),返回。
void draw(double length)
{
if(length<3)return;
for(int i=1;i<=3;i++)
{
draw(length/2);
pen.fd(length);
pen.lt(120);
}
}
int main()
{
pen.move(-100,-100);
pen.rt(90);
draw(300);
return 0;
}
可以得到谢尔宾斯基三角形:

谢尔宾斯基三角形
拓展:绘制其他分形图。