导航:首页 > 源码编译 > 递归算法过程

递归算法过程

发布时间:2023-01-05 08:24:05

1. 什么是递归算法

递归算法就是一个函数通过不断对自己的调用而求得最终结果的一种思维巧妙但是开销很大的算法。
比如:
汉诺塔的递归算法:
void move(char x,char y){
printf("%c-->%c\n",x,y);
}

void hanoi(int n,char one,char two,char three){
/*将n个盘从one座借助two座,移到three座*/
if(n==1) move(one,three);
else{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}

main(){
int n;
printf("input the number of diskes:");
scanf("%d",&n);
printf("The step to moving %3d diskes:\n",n);
hanoi(n,'A','B','C');
}
我说下递归的理解方法
首先:对于递归这一类函数,你不要纠结于他是干什么的,只要知道他的一个模糊功能是什么就行,等于把他想象成一个能实现某项功能的黑盒子,而不去管它的内部操作先,好,我们来看下汉诺塔是怎么样解决的
首先按我上面说的把递归函数想象成某个功能的黑盒子,void hanoi(int n,char one,char two,char three); 这个递归函数的功能是:能将n个由小到大放置的小长方形从one 位置,经过two位置 移动到three位置。那么你的主程序要解决的问题是要将m个的"汉诺块"由A借助B移动到C,根据我们上面说的汉诺塔的功能,我相信傻子也知道在主函数中写道:hanoi(m,A,B,C)就能实现将m个块由A借助B码放到C,对吧?所以,mian函数里面有hanoi(m,'A','C','B');这个调用。
接下来我们看看要实现hannoi的这个功能,hannoi函数应该干些什么?
在hannoi函数里有这么三行
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
同样以黑盒子的思想看待他,要想把n个块由A经过B搬到C去,是不是可以分为上面三步呢?
这三部是:第一步将除了最后最长的那一块以外的n-1块由one位置经由three搬到two 也就是从A由C搬到B 然后把最下面最长那一块用move函数把他从A直接搬到C 完事后 第三步再次将刚刚的n-1块借助hannoi函数的功能从B由A搬回到C 这样的三步实习了n块由A经过B到C这样一个功能,同样你不用纠结于hanoi函数到底如何实现这个功能的,只要知道他有这么一个神奇的功能就行
最后:递归都有收尾的时候对吧,收尾就是当只有一块的时候汉诺塔怎么个玩法呢?很简单吧,直接把那一块有Amove到C我们就完成了,所以hanoni这个函数最后还要加上 if(n==1)move(one,three);(当只有一块时,直接有Amove到C位置就行)这么一个条件就能实现hanoin函数n>=1时将n个块由A经由B搬到C的完整功能了。
递归这个复杂的思想就是这样简单解决的,呵呵 不知道你看懂没?纯手打,希望能帮你理解递归
总结起来就是不要管递归的具体实现细节步骤,只要知道他的功能是什么,然后利用他自己的功能通过调用他自己去解决自己的功能(好绕口啊,日)最后加上一个极限情况的条件即可,比如上面说的1个的情况。

2. 一个递归算法必须包括什么

递归算法包含的两个部分:

1、由其自身定义的与原始问题类似的更小规模的子问题(只有数据规模不同),它使递归过程持续进行,称为一般条件。

2、所描述问题的最简单的情况,它是一个能控制递归过程结束的条件,称为基本条件。(递归出口)

递归的定义:

如果一个对象部分地由它自身组成或按它自己定义,则称它是递归的,所以说递归就是函数/过程/子过程在运行过程中直接或间接调用自身而产生的重入现象。

递归的基本思想:

就是把一个规模大的问题分为若干个规模较小的子问题求解,而每一个子问题又可以分为几个规模更小的子问题。基本上,所有的递归问题都可以用递推公式来表示。

最重要的一点就是假设子问题已经解决了,现在要基于已经解决的子问题来解决当前问题;或者说,必须先解决子问题,再基于子问题来解决当前问题或者可以这么理解:递归解决的是有依赖顺序关系的多个问题。

递归的优缺点:

优点:逻辑清楚,结构清晰,可读性好,代码简洁,效率高(拓展:DFS深度优先搜素,前中后序二叉树遍历)

缺点:函数调用开销大,空间复杂度高,有堆栈溢出的风险

3. 递归算法 求详细过程

递归算法是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
递归算法要求
递归算法所体现的“重复”一般有三个要求:
一是每次调用在规模上都有所缩小(通常是减半);
二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。
举例
描述:把一个整数按n(2<=n<=20)进制表示出来,并保存在给定字符串中。比如121用二进制表示得到结果为:“1111001”。
参数说明:s: 保存转换后得到的结果。
n: 待转换的整数。
b: n进制(2<=n<=20)
void
numbconv(char *s, int n, int b)
{
int len;
if(n == 0) {
strcpy(s, "");
return;
}
/* figure out first n-1 digits */
numbconv(s, n/b, b);
/* add last digit */
len = strlen(s);
s[len] = ""[n%b];
s[len+1] = '\0';
}
void
main(void)
{
char s[20];
int i, base;
FILE *fin, *fout;
fin = fopen("palsquare . in", "r");
fout = fopen("palsquare.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%d", &base);
/*PLS set START and END*/
for(i=START; i <= END; i++) {
numbconv(s, i*i, base);
fprintf(fout, "%s\n", s);
}
exit(0);
}
C#:例子
例:一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少。
public class MainClass
{
public static void Main()
{
Console.WriteLine(Foo(30));
}
public static int Foo(int i)
{
if (i <= 0)
return 0;
else if(i > 0 && i <= 2)
return 1;
else return Foo(i -1) + Foo(i - 2);
}
}

4. 递归算法是怎么运行的

递归算法是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
一个过程(或函数)直接或间接调用自己本身,这种过程(或函数)叫递归过程(或函数)。
递归算法
递归算法流程
递归过程一般通过函数或子过程来实现。递归方法:在函数或子过程的内部,直接或者间接地调用自己的算法。

算法简析
递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方,采用递归编写
递归能使程序变得简洁和清晰。

5. 汉诺塔递归算法是什么

hanot (n-1,b,a,c);(解释:在把B塔上的(n-1))个借助A塔移动到C塔)

为了实现 n个盘从 借助c 从a 移动到 b

思路如下:

首先考虑极限当只有一个盘的时候,盘直接从 a -> b即可。

当有2个盘的时候,把1号盘从a -> c 然后 把2号盘 a->b 再 把 2好盘从 c - > b。

当有n个盘的时候,把 n-1个 盘 借助 b 移动到 c 然后将 n号盘从 a -> b。

这时候只要将 n-1想办法从c移动到 b 借助 a 那么就可以先把 n-2个盘借助b移动到a。

递归,就是在运行的过程中调用自己。

构成递归需具备的条件:

1,子问题须与原始问题为同样的事,且更为简单;

2,不能无限制地调用本身,须有个出口,化简为非递归状况处理。

在数学和计算机科学中,递归指由一种(或多种)简单的基本情况定义的一类对象或方法,并规定其他所有情况都能被还原为其基本情况。

以上内容参考:网络-递归公式

6. 六、递归与回溯算法

在计算机领域里面,很多问题都可以要采用递归算法来解决。递归中,最长用到的方法就是回溯法。我们具体分析问题的时候,可以发现这类问题本质是一个树的形状。

递归算法的本质还是将原来的问题转化为了更小的同一问题,进行解决。一般注意两点:
1、递归终止的条件。对应到了递归算法中最基本的问题,也是最最简单的问题。
2、递归过程。递归过程需要将原问题一步一步的推到更小的 同一 问题,更小的意思就是子问题解决起来就更加的简单。有写情况是能够找到一个递推的公式的。这个过程中就需要透彻的去理解递归函数的意义。明确这个函数的输入和输出是什么,这样来写的话,就清晰多了。

因为有了这样的递归公式,那么我们就很容易的能看出来递归的终止条件就是我们知道的f(0)和f(1)了。有了f(0)和f(1)之后,我们就能够继续的递推出f(3)一直到f(n)了。

但是我们现在才用一个递归算法的思想来解决这个问题:

像我们常见的数据结构如链表、树、图等都是有着天然的递归结构的,链表由于是一个线性的结构,那么通常我们也是能够直接循环遍历就能解决问题的,但是这里我们用递归法来解决一下LeetCode上面的问题
LeetCode 203 移除链表元素
分析:链表的结构可以理解成一个节点连接这一个更短的链表,这样依次一直看下去,直到最后一个节点None,那么我们这个时候的递归终止条件就是head指向None了,返回的就是None

深入的理解递归算法之后,我们就开始进行回溯法的学习。通过LeetCode上面的几道题,我们来深入的探讨一下递归与回溯法的应用。

持续更新中...
数据结构与算法系列博客:
一、数据结构与算法概述
二、数组及LeetCode典型题目分析
三、链表(Linked list)以及LeetCode题
四、栈与队列(Stack and Queue
五、树(Trees)
六、递归与回溯算法
七、动态规划
八、排序与搜索
九、哈希表

参考资料
1、
2、
3、

7. 递归算法的执行过程,一般来说,可先后分成哪两个阶段

递归算法的执行过程,一般来说,可先后分成“递推”与“回归”两个阶段。

8. 什么是递归

程序调用自身就叫做递归。
递归一般用来算一些比较麻烦的算法问题。
递归跟循环的区别,循环注重过程,而递归值注重结果。
简单的来说就是:用循环能实现的,递归一般可以实现,但是能用递归实现的,循环不一定能。因为有些题目①只注重循环的结束条件和循环过程,而往往这个结束条件不易表达(也就是说用循环并不好写);②只注重循环的次数而不注重循环的开始条件和结束条件(这个循环更加无从下手了)。
要想理解递归一时半会也弄不明白。但是写递归需要记住三个步骤。
1.首先去找临界值,即无需计算,获得的值。
2. 找这一次和上一次的关系
3. 假设当前函数已经可以使用,调用自身计算上一次和这一次的关系。

9. java中递归算法是怎么算的

1.汉诺塔问题
import javax.swing.JOptionPane;
public class Hanoi {
private static final String DISK_B = "diskB";
private static final String DISK_C = "diskC";
private static final String DISK_A = "diskA";
static String from=DISK_A;
static String to=DISK_C;
static String mid=DISK_B;
public static void main(String[] args) {
String input=JOptionPane.showInputDialog("please input the number of the disks you want me move.");
int num=Integer.parseInt(input);
move(num,from,mid,to);
}
private static void move(int num, String from2, String mid2, String to2) {
if(num==1){
System.out.println("move disk 1 from "+from2+" to "+to2);
}
else {
move(num-1,from2,to2,mid2);
System.out.println("move disk "+num+" from "+from2+" to "+to2);
move(num-1,mid2,from2,to2);
}
}
}
2. 这是一个排列的例子,它所做的工作是将输入的一个字符串中的所有元素进行排序并输出,例如:你给出的参数是"abc" 则程序会输出:
abc
acb
bac
bca
cab
cba
(1)算法的出口在于:low=high也就是现在给出的排列元素只有一个时。
(2)算法的逼近过程:先确定排列的第一位元素,也就是循环中i所代表的元素,
然后low+1开始减少排列元素,如此下去,直到low=high
public static void permute(String str) {
char[] strArray = str.toCharArray();
permute(strArray, 0, strArray.length - 1);
}
public static void permute(char[] list, int low, int high) {
int i;
if (low == high) {
String cout = "";
for (i = 0; i<= high; i++)
cout += list[i];
System.out.println(cout);
} else {
for (i = low; i<= high; i++) {
char temp = list[low];
list[low] = list[i];
list[i] = temp;
permute(list, low + 1, high);
temp = list[low];
list[low] = list[i];
list[i] = temp;
}
}
}
3。这是一个组合的例子,与上述的例子相似,只是它所做的工作是,输出所给字符串中制定数目的元素的组合种类
(1)程序出口在于n=1,此时只要输出目标数组的所有元素即可
(2)逼近过程,当n>1的时候,我们先取第一个元素放入目标数组中,然后n-1,如此下去,最后出来。
import javax.swing.JOptionPane;
public class Combination {
/**
* @param args
*/
public static void main(String[] args) {
String input = JOptionPane.showInputDialog("please input your String: ");
String numString = JOptionPane.showInputDialog("please input the number of your Combination: ");
int num = Integer.parseInt(numString);
Combine(input, num);
}
private static void Combine(String input, int num) {
char[] a = input.toCharArray();
String b = "";
Combine(a, num, b, 0, a.length);
}
private static void Combine(char[] a, int num, String b, int low, int high) {
if (num == 0) {
System.out.println(b);
} else {
for (int i = low; i<a.length; i++) {
b += a[i];
Combine(a, num - 1, b, i+1, a.length);
b=b.substring(0, b.length()-1);
}
}
}
}

阅读全文

与递归算法过程相关的资料

热点内容
mac压缩解压视频 浏览:906
这就是程序员魅力 浏览:296
京东java算法笔试题 浏览:178
柱子加密箍筋不准有接头 浏览:199
我的世界服务器菜单插件如何使用 浏览:12
刘毅10000词pdf 浏览:890
刚毕业的程序员会什么 浏览:974
单片机控制64路开关量 浏览:982
win10截图编程 浏览:420
怎样把名字变成文件夹 浏览:203
文件怎么搞成文件夹 浏览:730
多线程编程php 浏览:606
安卓机越用越卡有什么办法 浏览:17
高中生解压操场适合做的游戏 浏览:395
程序员java招聘 浏览:462
未来之光手机云服务器 浏览:160
服务器下载资料为什么c盘满了 浏览:265
怎么清除空文件夹 浏览:544
如何查看派派服务器 浏览:804
杀手6解压画面 浏览:671