《算法笔记》第4章 入门篇(2)—算法初步 4.3递归(C/C++)

本文介绍了使用递归方法解决四个经典算法问题:计算阶乘、获取斐波那契数列的第n项、生成全排列及解决n皇后问题。通过递归和分治策略,展示了如何高效地处理这些计算挑战,并给出了详细的C++代码实现和运行结果。
摘要由CSDN通过智能技术生成

《算法笔记》第4章 入门篇(2)—算法初步

4.3递归

4.3.1分治

无(O_O)

4.3.2递归

1.使用递归求解n的阶乘
代码如下:
#include<cstdio>
using namespace std;
//n!的计算式:1*2*3*...*(n-1)*n
//n!的计算式的递推形式:(n-1)!*n
//令F(n)表示n!,则递归式:F(n) = F(n-1) * n;
//递归边界:F(0)=1(因为0! = 1) 
//定义返回值为int型的F(int n)函数,用于递归计算n!
int F(int n){
	//判断n是否等于0 
	if(n == 0){//到达递归边界F(0)时 
		return 1;//返回1 
	}else{//没有到达递归边界F(0)时 
		return F(n-1) * n;//使用递归式递归下去 
	}
}
int main(){
	//n的范围为:n<=16
	//当n为大于16的整数时,计算n!会产生溢出,
	//如17!已经超出了int型的数据范围 
	int n;//定义整型变量n 
	scanf("%d", &n);//输入n 
	printf("%d\n", F(n));//输出递归计算n!后的结果 
	return 0;
} 
运行结果如下:

在这里插入图片描述

2.求Fibonacci数列的第n项
代码如下:
#include<cstdio>
using namespace std;
//递归式:F(n) = F(n-1) + F(n-2) 
//递归边界:F(0) = 1; F(1) = 1 
//定义返回值为int型的F(int n)函数,用于递归计算数列的第n项 
int F(int n){
	//判断n是否等于0或n是否等于1 
	if((n == 0) || (n == 1)){//到达递归边界F(0)或F(1)时 
		return 1;//返回1 
	}else{//到达递归边界F(0)或F(1)时
		return F(n-1) + F(n-2);//使用递归式递归下去 
	}
} 
int main(){
	//n的范围:n>=0,n可以理解为数组的下标 
	int n;//定义整型变量n,表示数列的第n项 
	scanf("%d", &n);//输入n 
	printf("%d\n", F(n));//输出数列的第n项的值 
	return 0;
} 
运行结果如下:

在这里插入图片描述

3.全排列
代码如下:
#include<cstdio>
using namespace std;
const int maxn = 11;//maxn表示数组P和hashTable的长度
int n;//n表示1到n的全排列 
int P[maxn];//数组P用于存储当前排列
//数组hashTable用于记录整数x在P[0]到P[index-1]中是否出现过 
bool hashTable[maxn] = {false};//默认1到n的所有整数均未出现过 
//处理当前排列的第index号位 
void generateP(int index){
	if(index == (n + 1)){//到达递归边界index=(n+1)时
		//通过循环输出当前排列 
		for(int i = 1; i <= n; i++){
			printf("%d", P[i]);
		}
		printf("\n");//输出换行 
		return;
	}
	//通过循环枚举1到n,将整数x填入P[index] 
	for(int x = 1; x <= n; x++){//每趟循环可表示当前排列的第一个数字为x 
		if(hashTable[x] == false){//x不在P[0]到P[index-1]中
			P[index] = x;//将x存储至P[index]中
			hashTable[x] = true;//记录x已经在数组P中
			generateP(index+1);//递归处理当前排列的第(index+1)号位
			hashTable[x] = false;//消除x在数组P中的记录,表示已经处理完P[index]为x的子问题	 
		}
	}
}
int main(){
	n = 3;//求1到3的全排列	
	generateP(1);//处理当前排列的第1号位
	return 0;
} 
运行结果如下:

在这里插入图片描述

4.n皇后问题
(1)暴力法
代码如下:
#include<cstdio>
#include<cmath> 
using namespace std;
const int maxn = 11;//maxn表示数组P和hashTable的长度
int n;//n表示在棋盘上放置n个皇后 
int P[maxn];//数组P用于存储当前排列
//数组hashTable用于记录整数x在P[0]到P[index-1]中是否出现过 
bool hashTable[maxn] = {false};//默认1到n的所有整数均未出现过 
int count = 0;//count表示合法的排列方案数 
//处理当前排列的第index号位 
void generateP(int index){
	if(index == (n + 1)){//到达递归边界index=(n+1)时
		bool flag = true;//默认当前排列为合法排列
		//通过循环遍历任意两个皇后来判断当前排列是否合法 
		for(int i = 1; i <= n; i++){
			for(int j = (i + 1); j <= n; j++){
				if(abs(i - j) == abs(P[i] - P[j])){//存在两个皇后在同一对角线上 
					flag = false;//表示当前排列不是合法排列					
				}
			}
		}
		if(flag){//当前排列为合法排列时 
			count++;//合法的排列方案数自增1 
		}
		return;
	}
	//通过循环枚举1到n,将整数x填入P[index] 
	for(int x = 1; x <= n; x++){//每趟循环可表示当前排列的第一个数字为x 
		if(hashTable[x] == false){//x不在P[0]到P[index-1]中
			P[index] = x;//将x存储至P[index]中
			hashTable[x] = true;//记录x已经在数组P中
			generateP(index+1);//递归处理当前排列的第(index+1)号位
			hashTable[x] = false;//消除x在数组P中的记录,表示已经处理完P[index]为x的子问题	 
		}
	}
}
int main(){
	n = 8;//在棋盘上放置8个皇后 
	generateP(1);//处理当前排列的第1号位
	printf("放置%d个皇后的合法方案数为:%d\n", n, count);//输出合法方案数 
	return 0;
} 
运行结果如下:

在这里插入图片描述

(2)回溯法
代码如下:
#include<cstdio>
#include<cmath> 
using namespace std;
const int maxn = 11;//maxn表示数组P和hashTable的长度
int n;//n表示在棋盘上放置n个皇后 
int P[maxn];//数组P用于存储当前排列
//数组hashTable用于记录整数x在P[0]到P[index-1]中是否出现过 
bool hashTable[maxn] = {false};//默认1到n的所有整数均未出现过 
int count = 0;//count表示合法的排列方案数 
//处理当前排列的第index号位 
void generateP(int index){
	if(index == (n + 1)){//到达递归边界index=(n+1)时
		//能够到达递归边界的当前排列一定是合法的 
		count++;//合法的排列方案数自增1
		return;
	}
	//通过循环枚举1到n,将整数x填入P[index] 
	for(int x = 1; x <= n; x++){//每趟循环可表示当前排列的第一个数字为x 
		if(hashTable[x] == false){//x不在P[0]到P[index-1]中
			bool flag = true;//flag表示当前皇后是否会和之前的皇后冲突,默认为不会冲突
			//通过循环遍历之前的皇后来判断当前皇后是否与之前皇后有冲突
			for(int pre = 1; pre < index; pre++){
				//第index列皇后的行号为x;第pre列皇后的行号为P[pre} 
				if(abs(index - pre) == abs(x - P[pre])){//当前皇后与之前的某一皇后在同一对角线上 
					flag = false;//当前皇后与之前皇后存在冲突
					break;//退出循环 
				}
			} 
			if(flag){//当前皇后与之前的皇后不存在冲突时 
				P[index] = x;//将x存储至P[index]中
				hashTable[x] = true;//记录x已经在数组P中
				generateP(index+1);//递归处理当前排列的第(index+1)号位
				hashTable[x] = false;//消除x在数组P中的记录,表示已经处理完P[index]为x的子问题	
			} 
		}
	}
}
int main(){
	n = 8;//在棋盘上放置8个皇后 
	generateP(1);//处理当前排列的第1号位
	printf("放置%d个皇后的合法方案数为:%d\n", n, count);//输出合法方案数 
	return 0;
} 
运行结果如下:

在这里插入图片描述

参考资料如下:

[1] 胡凡,曾磊.算法笔记[M].北京:机械工业出版社,2022:85-98.
[2] codeup网址:http://codeup.hustoj.com
[3] PAT网址:https://www.patest.cn/practice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值