递归与图形中的应用
递归的理解
在一长段时间内,我对递归和循环一直没有理清楚,在此以此篇文章梳理一下递归的思路,以供自己复习和他人借鉴。
递归的本质是自己调用自己,所以我们要有一个本体,可以进行调用,然后递归需要规定界限,否则就会走向无限,我们认为在这样的一个界限下需要结束递归;我们还需要在调用时有递推关系,否则就会陷入死循环,至此递归的三要素已经完整了。
而递归的运作过程是什么呢,和循环又有什么联系和区别呢?
首先我们在开始时触发递归的条件,即让本体满足条件,然后用本体通过递推关系表达出下一个过程体,让过程体通过递归实现与本体逻辑一致的方法,再次判断递归条件,然后递归调用这种抽象的方法,直至不满足条件,这个时候我们就走到头了,需要折返,回到上一个过程体中进行下一语句的指令,直至回到整个递归结束。
由此可见,递归过程中实际上进行了多次递归操作,递归的对象是一个个套娃的过程体,但是这种抽象的方法是一致的,所以我们才归纳出这种操作方法。
同时它与循环的联系就凸显了,由于对这种抽象方法需要反复调用,所以我们需要循环来体现递推关系,同时我们需要分支,区分正常的进行递归和递归终止,我们就可以利用if语句和递归条件,最终实现我们的功能。
对现实问题进行递归方法的抽象
以下我们以递归分型图形的实现为例子具体讲解递归方法的抽象以及加深对递归的理解。
- 问题:绘制如下图形:
我们以右边的方形为例子,我们需要对这个图形进行整体和部分寻找到相同的属性,我们可以观察到,每个框中由一个中间的实心大正方形和周围八个没有被填满的正方形构成。
然后在每个没有被填满的边框中,此时,那个没有完全填满的正方形成为这个框的中心,可以视为又把边框9等分,中心的正方形又被填满了,我们又继续向更小的块进行相同的操作。
通过分析,我们找到了这个不变的抽象方法:把对象进行9等分,然后周围放置8个较小的正方形,之后依次把每个小正方形框定成中心正方形,直到最后的小正方形的边长小于我们的标定值。那么我们可以如下进行实现:
public void drawRec(Graphics g, int x, int y, int h, int w) {
g.fillRect(x + w, y + h, w, h);//g是一个画笔对象,
//表示对显示框中的画笔进行操作
if (h < 10) {
return;
} else {
int temp =x;//保持第一列
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 3; i++) {
drawRec(g, x , y , w / 3, h / 3);//边长缩小,
//参考系原点不变
x+=w;//绘制下一列的方形,改变参考系原点
}
x=temp;//回到第一列
y+=w;//绘制下一行,同样改变参考系原点
}
}
}
最后的效果图如下:
注:1.坐标原点是左上角,横向为x轴正方向,纵向是y轴正方向。