算法基础—递归(一)

递归(一)

递归的基本概念
▲一个函数调用其自身,就是递归
●求n!的递归函数

#include <iostream>
using namespace std;
int Factorial(int n)
{
	if (n == 0)
		return 1;
	else
		return n * Factorial(n - 1);
}
int main()
{
	cout << Factorial(3) << endl;
	return 0;
}

结果:6
在这里插入图片描述
递归和普通函数调用一样是通过栈实现的

●汉诺塔问题

有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘;大盘不能叠在小盘上面。 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。问:如何移?最少要移动多少次?
汉诺塔示意图如下:

汉诺塔问题
三个盘的移动
汉诺塔三个盘的移动
解法:

解法的基本思想是递归。假设有A、B、C三个塔,A塔有N块盘,目标是把这些盘全部移到C塔。那么先把A塔顶部的N-1块盘移动到B塔,再把A塔剩下的大盘移到C,最后把B塔的N-1块盘移到C。每次移动多于一块盘时,则再次使用上述算法来移动。

输入

输入为一个整数后面跟三个单字符字符串。 整数为盘子的数目,后三个字符表示三个杆子的编号

输出

输出每一步移动盘子的记录。一次移动一行。 每次移动的记录为例如3:a->b 的形式,即把编号为3的盘子从a杆移至b杆。我们约定圆盘从小到大编号为1, 2, …n。即最上面那个最小的圆盘编号为1,最下面最大的圆盘编号为n。

样例输入
3 a b c
样例输出
1:a->c
2:a->b
1:c->b
3:a->c
1:b->a
2:b->c
1:a->c

#include <iostream>
using namespace std;
void Hanoi(int n, char src, char mid, char dest,int src_n)
{   //将src座上的n个盘子,以mid座位中转,移动到dest座
	//题目要求输出前有盘子编号 令src座上最上方盘子编号是src_n
	if (n == 1)//当只有一个盘子的时候
	{   
		//直接将这一个盘子从src移动到dest即可
		cout << src_n << ":" << src << "->" << dest << endl;
		return;
	}
	Hanoi(n - 1, src, dest, mid, src_n);//先将n-1个盘子从src移动到mid
	cout << src_n + n - 1 << ":" << src << "->" << dest << endl;
	//再将一个盘子从src移动到dest
	Hanoi(n - 1, mid, src, dest, src_n);//最后将这n-1个盘子从mid移动到dest
	return;
}
int main()
{
	char a, b, c;
	int n;
	cin >> n >> a >> b >> c;
	Hanoi(n, a, b, c, 1);
	return 0;
}

汉诺塔输出结果
递归的作用

  • 替代多重循环
  • 解决本来就是用递归形式定义的问题
  • 将问题分解为规模更小的子问题进行求解 …

●N皇后问题

用递归替代多重循环
n皇后问题:输入整数n,要求n个国际象棋的皇后,摆在n*n的棋盘上,互相不能攻击,输出全部方案。
八皇后问题:八重循环。n皇后,n重循环?
递归解决!!!
【问题描述】

输入一个正整数N,则程序输出N皇后问题的全部摆法。输出结果里面的每一行都代表一种摆法。行里的第i个数字如果是n,就代表第i行的皇后应该放在第n列。皇后的行、列编号都是从1开始算。

样例输入
4
样例输出
2 4 1 3
3 1 4 2

#include <iostream>
#include <cmath>
using namespace std;
int N;
int queenPos[100];
//用来存放算好的皇后位置 最左上角是(0,0)
void NQueen(int k)
{
	//在0~k-1行的皇后已经摆好的情况下,摆第k行及其后的皇后
	int i;
	if (k == N)//k个皇后已经摆好
	{
		for (i = 0; i < N; i++)
			cout << queenPos[i] + 1 << " ";//+1时候是因为列号行号都从1开始
		cout << endl;
		return;
	}
	for (i = 0; i < N; i++)//逐个尝试第k个皇后的位置
	{
		int j;
		for (j = 0; j < k; j++)
		{
			//和已经摆好的k个皇后的位置比较,看是否冲突
			if (queenPos[j] == i || abs(queenPos[j] - i) == abs(k - j))
			{
				break; //冲突,则试下一个位置
			}
		}
		if (j == k)//当前选的位置i不冲突
		{
			queenPos[k] = i;//将第k个皇后摆放在位置i
			NQueen(k + 1);
		}
	}//for(i=0;i<N;i++)
}
int main()
{
	cin >> N;
	NQueen(0);//从第0行开始摆皇后
	return 0;
}

N皇后问题

●逆波兰表达式

用递归解决递归形式的问题

  1. 一个数是一个逆波兰表达式,值为该数
  2. “运算符 逆波兰表达式 逆波兰表达式”是逆波兰表达式,值为两个逆波兰表达式的值运算的结果
  3. 一般教科书上将本题中的“逆波兰表达式”称为“波兰表达式”,而将运算符后置的表达式称为“逆波兰表达式”

逆波兰表达式是一种把运算法前置的算术表达式,例如普通的表达式2 + 3的逆波兰表达式表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) x 4的逆波兰表示法为 x + 2 3 4。本题求解逆波兰表达式的值,其中运算符包括 + - * /四个。

输入

输入为一行,其中运算符和运算数之间都用空格分割,运算数是浮点数

输出

输出为一行,表达式的值

样例输入
例: * + 11.0 12.0 + 24.0 35.0
样例输出
1357.000000
提示:(11.0+12.0)x(24.0+35.0)

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
double exp()
{
	//读入一个逆波兰表达式,并计算其值
	char s[20];
	cin >> s;
	switch (s[0])
	{
		case '+': return exp() + exp();
		case '-': return exp() - exp();
		case '*': return exp() * exp();
		case '/': return exp() / exp();
		default: return atof(s);//将字符串转化为浮点数
		break;
	}
}
int main()
{
	printf("%lf", exp());
	return 0;
}

在这里插入图片描述
下一篇链接:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值