递归二之:解决递归定义的问题

2,解决本来就是递归定义的问题:

本来就是递归定义的问题中,我们可以很明显的看出其中的定义的嵌套性,下面举两个例子进行说明。

问题1:求解逆波兰表达式

题目描述: 逆波兰表达式是一种把运算符前置的算术表达式(其实一般教科书上称这种表 达式为波兰表达式),例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰 表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如 (2 + 3) * 4的逆波兰表示法为* + 2 3 4。本题求解逆波兰表达式的值,其中运算符 包括+ - * /四个。详情请看:逆波兰表达式-维基百科

其实这里逆波兰表达式的定义形式我们可以看成是:运算符 逆波兰表达式 逆波兰表达式一个值也可以看成是一个逆波兰表达式。这将是逆波兰表达式递归运算的结束条件。

虽然逆波兰表达式很多时候是基于堆栈求解的,但是这里通过其定义的形式我们可以看出其定义本身就是一个递归形式的。即逆波兰表达式本身又含有逆波兰表达式。
求解过程:

1,输入一个字符串表示逆波兰表达式
2,根据这个字符串中的第一个字符来确定加减乘除运算
3,递归调用输入逆波兰表达式进行运算
4,直到输入的逆波兰没有加减乘除字符时,即达到了递归调用的边界条件,此时返回该值。

下面是使用C++实现的结果:

#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);		//将字符串转化为数字,在<cstdlib>中 
	} 
}

int main() {
    
    
	printf("%lf",exp());
	return 0;
}

运行结果:
在这里插入图片描述
PS:教科书中一般将运算符前置的称为波兰表达式,而后缀的才叫做逆波兰表达式,这和本题有点不一样哈,不过问题不大(#.#)。

问题2:表达式求值计算:

问题描述:输入为四则运算表达式,仅由整数、+、-、*、/ 、(、) 组成,没有空格,要求求其值。假设运算符结果都是整数 。"/"结果也是整数

可以发现:表达式本身就是一个递归定义的,我们可以这样认为:

表达式由项构成,项由因子构成,因子又由表达式或者整数构成。
表达式:项通过加减运算得到
项:因子通过乘除运算得到
因子:括号里的表达式或者是整数

下面通过图片来说明:
在这里插入图片描述
可以发现计算表达式本身含着计算项,而计算项又含着计算因子,计算因子反过来又需要计算项。因此可以发现这是一个递归嵌套调用的过程。

下面是C++的代码实现:

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;

int factor_value();		//求因子
int term_value();		//求项的值
int expression_value();	//求表达式的值

int main() {
    
    
	cout << expression_value() << endl;
	return 0;
}
/*--- 求一个表达式的值 ---*/
int expression_value() {
    
     
	int result = term_value();		//求第一项的值 

	while (true) {
    
    
		char op = cin.peek();		//从输入流中读取第一个字符,用来判断其符号类型 ,只是**查看,不是取出**
		if (op == '+' || op == '-')  {
    
     //如果该字符是+或-的话需要进行下一项的读取操作,并将该符号从输入流中拿走
			cin.get();				
			int value = term_value();	//读取下一项
			//对结果进行加减运算
			if (op == '+') 
				result += value;
			else 
				result -= value; 
		} else 
			break;	
	}
	return result;
}
/*--- 计算项的值 ---*/
int term_value() {
    
    
	int result = factor_value();	//求第一因子的值
	
	while (true) {
    
    
	 	char op = cin.peek();
	 	if (op == '*' || op == '/') {
    
    
	 		cin.get();
	 		int value = factor_value();
	 		if (op == '*') 
	 			result *= value;
	 		else 
	 			result /= value;
		 } else 
		 	break;
	}
	
	return result;
}
/*--- 计算因子的值 ---*/
int factor_value() {
    
    
	int result = 0;
	char c = cin.peek();
	if (c == '(') {
    
    	//如果是括号则需要进行项的运算
		cin.get();
		result = expression_value();
		cin.get();	//将输入流中的‘)’取走
	} else {
    
    
		while (isdigit(c)) {
    
    	//最后的因子是数字字符的情况
			result = 10 * result + c - '0';
			cin.get();
			c = cin.peek();
		}
	}
	
	return result;
}

运行结果:可以输出正确的结果。
在这里插入图片描述
递归的其他内容可以查看:
递归一之:替代多重循环
递归三之:将问题分解为更小规模

猜你喜欢

转载自blog.csdn.net/weixin_44184990/article/details/105174644