C语言聊递归

C语言聊递归

何为递归

在C/C++、Python、Java等编程语言中都有一系列的代码块,它们可以重复被利用,需要用的时候就可以把它们调用出来,它们有一个共同的名称:函数。递归可以分解为递与归,递就是将目标穿递出去,归就是将递传递出去的目标收回,这就叫归。递归就是反复调用自己,在一个函数中调用本身。递归是一种思想,将大问题分解为小问题,解决小问题之后归并到大问题之上。递归不是一种具体实现的方法。

为什么要用递归?

众所周知,用编程语言里的顺序结构、if、while、for就可以解决大部分问题,然而在大规模问题中,这些问题有相同问题结构,,他们就是由这一层的结果来得到下一层结果,然而他们却需要相当多的for、while、if来实现,这便会让代码量剧增。在编程语言的设计人员看来,就有一种思想可以解决此类问题,那就是递归了,递归可以用少量的代码来实现程序的多次计算。

什么问题可以用递归实现?

将大问题分解为小问题,有相同的子结构(这是大前提)。我将通过一些例子来具体分析,为什么这些问题能够用递归解决。递归用到了栈,就是先进后出。

经典问题

1、斐波那契数列在这里插入图片描述

当然这题可以用循环解决:

#include "stdio.h"
#define N 10
using namespace std;
int a[1000];
int main(){
	int x,i=1;
	scanf("%d",&x);
	for(i;i<=x;i++){		//循环计算每一个f(x)的值 
		if(i==1||i==2)
			a[i]=1;
		else
			a[i]=a[i-1]+a[i-2];
	} 
	printf("%d",a[x]);
    return 0;
}

经过数学总结,
在这里插入图片描述
有这个数学公式就可以得知当x=1或x=2时f(x)=1,当x>2时f(x)=f(x-1)+f(x-2),即f(x)等于前两项的和,然而前两项有分别等于它们前两项的和,f(x-1)+f(x-2)=f(x-3)+f(x-2)+f(x-3)+f(x-4)~~,一直计算就可以得到f(3)=f(2)+f(1)了
贴上代码:

#include "stdio.h"
int fb(int n){
	if(n==1 || n==2)		//当算到n==1、2时返回确切的值 
		return 1;
	else
		return fb(n-1)+fb(n-2);	
}
int main(){
	int x;
	scanf("%d",&x);		//从键盘读取x 
	printf("%d",fb(x));
	return 0;
}
2、汉诺塔问题

在这里插入图片描述
汉诺塔题目的计算次数是以非常大的,若以循环写的话那可真是太糟糕了,写三、四、五个汉诺塔还行,这个一旦多起来,啧啧啧,这谁顶得住啊。如果用递归写的话那就简单多了,思路为计算一个塔盘的时候只需要将A->C,2个塔盘的时候需要在一个塔盘的基础上先将小的塔盘移到B上即A->B,再将第二个塔盘移动到C上A->C,再将B->C,这样就完成了移动,第三,第四个,等等都在前面的基础上移动,如果有四个塔盘,那就需要先移动上面三个塔盘到B上,再将B上的塔盘移动到C上。汉诺塔的题目可得花时间来消化一下哦。
如下代码:

#include<stdio.h>
void hanoit(int n, char a, char b, char c) {
	if(n == 1)
		printf("%c-->%c\n", a,c);
	else{
		hanoit(n - 1, a, c, b);
		printf("%c-->%c\n",a,c);
		hanoit(n - 1, b, a, c);
	}
}
int main(){
	int m;
	scanf("%d", &m);
	hanoit(m,'A','B','C');
	return 0;
}
3、八皇后->N皇后问题

描述:

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

八皇后问题就是N=8的时候,这时要写八重循环来解决此问题,如果不是八,而是要从键盘中接受一个数字呢?那循环就难办了。

#include<stdio.h>
#include<cmath>
int N;
int qu[100];	//用于存放已算皇后的位置
void nQu(int k){//在k-1个皇后都摆好位置后摆第k个皇后 
	int i;
	if(k==N){	//计算完后 
		for(i=0;i<N;i++)
			printf("%d ",qu[i]+1);	//qu[i]+1是因为数组是从0开始的 
		printf("\n");
		return;
	}
	for(i=0;i<N;i++){		//尝试皇后的位置 
		int j;
		for(j=0;j<k;j++)
			if(qu[j]==i||abs(qu[j]-i)==abs(k-j))//与已摆好位置的皇后冲突,跳出 
				break;
		if(j==k){			//不冲突,将皇后摆在i的位置 
			qu[k]=i;
			nQu(k+1);
		}
	}
}
int main(){
	scanf("%d",&N);
	nQu(0);
	return 0;
}
4、其他

阶乘、逆波兰表达式、上楼梯等问题

如何运用递归

1、找到临界条件
2、满足条件就跳出
3、有进有出(就是递进了多少层,就得返回多少层)
4、不能无限递归,不然会爆栈

注意:递归并不能优化时间复杂度,并且如果问题的规模相当的大,还有可能爆栈!

[^1]这是我以自己的理解来解释递归,如果与他人不同,望见谅!如有纰漏,望指教,谢谢!
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值