什么是递归与递归分形

2023-11-12 02:10
文章标签 递归 分形

本文主要是介绍什么是递归与递归分形,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文,将会讨论在程序中的递归,迭代,分形递归。

什么是递归

一个事物由这个事物的本身所构建,那么在理解这个事物的时候,就需要理解这个事物的构造方式,那么就需要回到理解这个事物的本身,从而再次需要理解这个事物的构成……这个不断循环理解的过程就形成了递归

首先,更通俗的来讲,递归这个概念,其中的“”就代表传递,“”就代表着回归。例如:现在有A和B两个地点,而B地恰好有一个哆啦A梦的任意门,那么我们从A点走到B点后就会立即被传送到A点,这样就完成了一次循环。而不断完成这个循环的过程,是递归的重要要素——循环嵌套

其次,递归还有另一个重要要素——自身构建。正如前面所提到,我们在理解这个事物时需要理解这个事物的构造方式。这在程序中就体现为,每一次循环嵌套里都有同样的构建方式,但可能构建方式中包含的内容、数据发生了变化。例如:仍旧是A和B点两个地点和一个任意门,这一次,每当我们传过任意门,依然会被传送到A点,但B点和任意门的位置会变化到初始A、B两地的中点位置。这里的位置变换就是循环嵌套中的构建方式,而构建方式的内容、数据就是B点的位置。所以每一次递归完成后,都会生成一个新的B点位置,并回归到新的循环嵌套中。

最后,递归是可以有出口的。什么意思呢?在前面的案例中,如果我们持续从A走向B,会出现无限循环,这个递归是无限循环嵌套的。那我们如果想让递归终止,则需要一个让递归终止的条件(本例中为递归次数),满足条件后,也就完成了最后一次递归,找到了递归的出口。而同时,递归终止就会开始回溯,从最后一循环逐渐返回上一层,这代表事物层层回归。这很像双多米诺骨牌效应(Double Domino Effect, 如下图),这种效应会在把相邻多米诺骨牌的间距控制为骨牌的高度时发生,当第1块砖块被推倒,带动随后的砖块一起倾倒,当最后一块砖倒在地面,就会开始“回溯”的过程,最终从第n块砖到第1块砖逐次倒在地面上。这就好比递归获取到最后一层的结果后,逐层传回的过程。

Double Domino Effect:
Double Domino Effect

如果上述例子使用JAVA编程实现,则形如:

public class Recursion {//递归public void position(double a, double b,int i) {if(i<0) {return;} //这里i代表递归的次数i--;double new_b = b*0.5; //递归的自身构建方法System.out.println(a+"+"+new_b);position(a,new_b,i); //进入下一层递归,将新的数据b传入}//主函数public static void main (String[] args) {Recursion p= new Recursion(); p.position(0, 100, 10);//调用递归方法,赋予a,b,i属性}
}

这就形成了一个最简单的递归,程序按照我们既定的方法完成10次循环,且每次循环都输出一个为B点坐标值(这里为一维坐标系)一半的值。

例:用递归求数的阶乘:

public static long factorial(int n) throws Exception {if (n < 0)throw new Exception("参数不能为负!");else if (n == 1 || n == 0)return 1;elsereturn n * factorial(n - 1);
}

迭代与递归的区别

我们通过一个例子,来了解迭代与递归,在处理同一个任务时,会有什么不同。这个任务的目标是追到女神。

首先,迭代循环——是整体视角,它可以看清整体变化的过程。

这意味着高屋建瓴地把追到女神,分为若干个步骤,这些步骤可以一样也可以不一样,如送礼物、看电影、请吃饭等等。然后,一个步骤的执行就是一次迭代,即循环了一次。直到循环结束,如迭代了520次,女神就必定追到了。

可以看到,在520次的迭代中,每次迭代的结果都是明确的,都比上一次更加接近目标,并且也不依赖下一次的迭代,但可能会依赖上一次——比如上一次看电影了,这一次就不会再看电影。

其次,递归循环——是局部视角,它无法看清整体变化的过程。

这意味着无法知道经历几次循环,才可以追到女神,只是不断重复同样的操作,如热切的尬聊,但每次尬聊可以发生在不同的场景和时间,如餐厅、郊游、雨天、深夜等等,以及聊不同的内容,即:操作相同,数据不同。直到女神,在一次尬聊中,回复了520,就代表递归的结束,即追到女神了。

而在之前的AB门穿越事件中,示例代码使用了递归的次数作为递归的出口,满足次数即结束递归循环,这里递归循环和迭代循环是一样的。而在递归求数的阶乘中,这个循环的出口是相对未知的,无法知道几次循环才可以求得当前输入的阶乘。那么综上可见,迭代与递归,有时是可以相互转换的,有时却是不行的,主要是整体与局部视角的不同

什么是分形

分形——通常被定义为一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状,即具有自相似的性质。例如,雪花、晶体、弯弯曲曲的海岸线、起伏不平的山脉等等。

曼德尔球分形:
曼德尔球分形

递归分形

正如分形的定义所言,分形的每一部分都是整体缩小后的形状,可以想象,这种表现在雪花上尤为直观。那么这就意味着,分形图像可以通过递归的方式来实现。

这里我们尝试用递归写一个谢尔宾斯基三角形。谢尔宾斯基三角形(Sierpinski triangle)是一种分形,由波兰数学家谢尔宾斯基在1915年提出。它是自相似集的例子。谢尔宾斯基三角形
思路:
1.取一个空心的三角形(这里用等腰三角形);
2.沿三边中点的连线,将它分成四个小三角形(其中,周围3个空心,中间1个实心);
3.对新出现的空心三角形重复执行第2步操作。

JAVA代码实现:

	public void drawTriangle(int x1, int y1, int dx, int dy, int i) {if (i<0) {return; // i 为循环次数,每层递减,小于0时返回}i--;int px[]= {x1,x1+dx,x1-dx,x1}; //X1, y1为顶点像素坐标,dx,dy为顶点到底角的距离int py[]= {y1,y1+dy,y1+dy,y1};g.drawPolygon(px,py,4); //绘制空心三角形int px1[]= {x1-dx/2,x1+dx/2,x1,x1-dx/2}; //取中点int py1[]= {y1+dy/2,y1+dy/2,y1+dy,y1+dy/2};g.fillPolygon(px1, py1, 4); //绘制实心三角形drawTriangle(x1-dx/2,y1+dy/2,dx/2,dy/2,i); //对新分出的左下角空心三角形递归drawTriangle(x1,y1,dx/2,dy/2,i); //对新分出的顶部三角形递归drawTriangle(x1+dx/2,y1+dy/2,dx/2,dy/2,i); //对新分出的右下角三角形递归	}

创建UI与绘图界面后,即可调用该方法实现绘制谢尔宾斯基三角形。

这篇关于什么是递归与递归分形的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/394368

相关文章

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

oracle11.2g递归查询(树形结构查询)

转自: 一 二 简单语法介绍 一、树型表结构:节点ID 上级ID 节点名称二、公式: select 节点ID,节点名称,levelfrom 表connect by prior 节点ID=上级节点IDstart with 上级节点ID=节点值 oracle官网解说 开发人员:SQL 递归: 在 Oracle Database 11g 第 2 版中查询层次结构数据的快速

Leetcode面试经典150题-128.最长连续序列-递归版本另解

之前写过一篇这个题的,但是可能代码比较复杂,这回来个简洁版的,这个是递归版本 可以看看之前的版本,两个版本面试用哪个都保过 解法都在代码里,不懂就留言或者私信 class Solution {/**对于之前的解法,我现在提供一共更优的解,但是这种可能会比较难懂一些(思想方面)代码其实是很简洁的,总体思想如下:不需要排序直接把所有数放入map,map的key是当前数字,value是当前数开始的

【UVA】10651-Pebble Solitaire(直接递归或者记忆化)

不知道这个题UVA的数据是怎么的,用2个方法交了,第一次直接递归,第二次记忆化剪枝,时间竟然一样!? 直接郁闷了,简单的二进制表示状态和二进制运算。 14145176 10651 Pebble Solitaire Accepted C++ 0.009 2014-09-04 09:18:21 #include<cstdio>#include<algorithm>#inclu

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

Winform中在窗体中的Paint事件中重绘会导致递归问题?

在 WinForms 应用程序中,如果在窗体的 Paint 事件处理程序中不断调用 Invalidate 方法,确实可能会导致递归调用的问题。这是因为每次调用 Invalidate 方法时,都会向消息队列添加一个绘制消息,当消息队列中的绘制消息被处理时,会触发 Paint 事件。如果 Paint 事件处理程序中又调用了 Invalidate,就会形成一个循环,导致递归调用 Paint 事件,这

每日OJ_牛客_求和(递归深搜)

目录 牛客_求和(递归深搜) 解析代码 牛客_求和(递归深搜) 求和_好未来笔试题_牛客网 解析代码         递归中每次累加一个新的数,如果累加和大于等于目标,结束递归。此时如果累加和正好等于目标,则打印组合。向上回退搜索其它组合。此题本身就是一个搜索的过程,找到所有的组合。 #include <iostream>#include <cmath>#in

归并排序-非递归实现

归并排序的非递归实现  我们可以把 一个数组 先拆分成 最小单元,这是分, 拆分成最小单元之后,我们对每个最小单元进行一次合并,这是治 最小单元 合并一次之后,我们继续 在上一次合并的基础上拆分,并且合并这是 合 , 直到 整个数组 只被拆成了两部分,在进行最终一次的和   我们画图举个例子 源代码如下,我们的merge的合并函数的参数是  原数组,左侧小数组索引位置开头,左侧小数

力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家

文章目录 一、递归二、区间动态规划 LeetCode:486. 预测赢家 一、递归 注意到本题数据范围为 1 < = n < = 20 1<=n<=20 1<=n<=20,因此可以使用递归枚举选择方式,时间复杂度为 2 20 = 1024 ∗ 1024 = 1048576 = 1.05 × 1 0 6 2^{20} = 1024*1024=1048576=1.05 × 10^