算法一:递归(二)(递归求阶乘、数制转换、计数、求和、求最大值)附如何书写企业级规范C格式

所谓递归算法,就是在程序中不断反复调用自身来求解问题的方法。这里强调的重点是调用自身,就得等待求解的问题能够分解为相同问题的一个子问题,这样通过多次递归调用,自己便可完成求解。

递归算法的具体实现过程一般通过函数(或子过程)来完成,在函数(或子过程)的内部,编写代码直接或者间接地调用函数(或子过程)自己,即可完成递归操作。这种函数也称为“递归函数”。在递归函数中,主调函数同时又是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层。

从递归算法的实质可以看出,递归算法也是一种循环,只是这种循环不是使用程序设计语言的循环语句来实现,而是循环调用函数(或子过程)自身来实现的。要实现这种递归循环,一般有三个要求:

  • 每循环调用一次,求解问题的规模都要有所缩小,即将求解的问题化为一个缩小了的子问题;

  • 相邻两次循环之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);

  • 当子问题的规模极小时,应该能直接给出解答而不再进行递归调用(即必须有一个结束递归的条件即递归出口),因而每次递归调用都是有条件的,无条件递归调用将会使程序进入死循环而不能正常结束(最终导致栈溢出)。

注意:

  • 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
  • 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
  • 在递归调用的过程中,系统将每一次递归调用的返回点、局部变量(临时变量)等保存在系统的栈中,当递归调用的次数太多时,就可能造成栈溢出错误。

例题一、求阶乘

理解递归算法最简单的例子就是:编写程序求n的阶乘(n!)。所谓阶乘,就是从1到指定数之间的所有自然数相乘的结果,或者说阶乘就是从数n到1之间的所有自然数相乘的结果,可写为以下算式:
n! = n * (n - 1) * (n - 2) * …* 2 *1
分解公式可得:
n的阶乘等于n乘以n-1的阶乘
n-1的阶乘分解为n-1乘以n-2的阶乘
这样,当将变量n逐步减小,到1时,就完成了递归操作,也就有了结束递归的条件

#include<stdio.h>

int f(int n){
	if(n <= 1)
		return 1;
	else
		return n * f(n - 1);
}

int main(){
	int n;
	printf("Please enter a digit:");
	scanf("%d", &n);
	printf("\n%d的阶乘结果为:%d\n", n, f(n));
	return 0;
}

部分运行结果如下:
在这里插入图片描述
以求6!为例简单分析递归调用过程:
在这里插入图片描述

企业级规范书写格式

/**************************************
* 
*版权所有(C)2020,Rihood 
*
*文件名称:guifan.cpp 
*内容摘要:用于示范变量和函数的规范化命名 
*其他说明:无
*当前版本:V1.0
*作    者:Rihood
*完成时期:2020.11.26
* 
* 
**************************************/

#include<stdio.h> 

typedef signed int INT32;				//重新定义数据类型 
typedef float FLOAT;					//重新定义数据类 

FLOAT ProcessFactorial(INT32 iInputValue);		//函数声明 
INT32 main(void); 							 	//函数声明 


/***************************************
* 
*功能描述:主函数
*输入参数:无
*输出参数:无
*返回值:无
*其他说明:无
*修改日期	版本号	修改人	修改内容 
*------------------------------------ 
*20201127	V1.0	Rihood	创建 
* 
***************************************/


INT32 main(void)
{
	INT32 iInputValue = 0;
	FLOAT fResult = 0.0;
	printf("input an integer number:");
	scanf("%d", &iInputValue);
	
	fResult = ProcessFactorial(iInputValue);		//调用求阶乘的函数 
	
	printf("%d != %6f\n", iInputValue, fResult);
	return 0;
}

/***************************************
* 
*功能描述:求一个数的阶乘
*输入参数:iInputValue输入值
*输出参数:无
*返回值:求阶乘后的结果
*其他说明:无
*修改日期	版本号	修改人	修改内容 
*------------------------------------ 
*20201127	V1.0	Rihood	创建 
* 
***************************************/

FLOAT ProcessFactorial(INT32 iInputValue)
{
	FLOAT fResult = 0.0;
	
	if(iInputValue < 0)
	{
		printf("iInputValue < 0, dataerror!");
		return -1;	
	} 
	else
	{
		if(iInputValue == 0 || iInputValue == 1)
		{										//0和1的阶乘是1 
			fResult = 1;
		}
		else
		{ 
			fResult = ProcessFactorial(iInputValue - 1)	* iInputValue;
		}
		
		return fResult;
	}
}

运行结果如下:
在这里插入图片描述

例题二、数制转换

将十进制整数转换为其他进制整数的计算过程是:将十进制数除以相应数制的基数,取其余数作为相应数制的最低位,再用商除以相应数制的基数,取余数作为相应数制的次低位……这样不断重复,即可完成转换。

例如,将十进制数121转换为二进制数的过程如下:
在这里插入图片描述
即(121)10 =(1111001)2

数制转换特点:

  • 在数制转换过程中有递归的结束条件,即当商为0时结束递归过程
  • 数制转换的过程是数据逐步变小的过程,即构成了递归调用中的“将问题化为一个缩小了的子问题”的特点

详细C代码如下:

#include<stdio.h>
#include<string.h>

void convto(char *s, int n, int b){
	char bit[] = {"0123456789ABCDEF"};
	int len;
	if(n == 0){
		strcpy(s, "");
		return;
	}
	convto(s, n / b, b);
	len = strlen(s);
	s[len] = bit[n % b];
	s[len + 1] = '\0';
}

int main(){
	char s[80];
	int i, base, old;
	printf("请输入十进制数:");
	scanf("%d", &old);
	printf("请输入转换的目标进制:");
	scanf("%d", &base);
	convto(s, old, base);
	printf("%s\n", s);
	return 0;	
} 

样例运行结果:
在这里插入图片描述
递归是个很难想出递归函数的算法,建议大家平时多做做递归方面的题熟悉套路

strcpy()函数就是把后面提供的内容赋值替换掉前面的内容,例如:

#include<stdio.h>
#include<string.h>

int main(){
	char s[80] = "123";
	strcpy(s, " 1");
	printf("%s\n", s);
	return 0;
}

运行结果如下:
在这里插入图片描述

例题三、递归求和

详细C++代码如下:

#include<iostream>
#include<vector>

using namespace std;

template<typename T>
T sum(vector<T> arr){
	if(arr.empty())
		return 0;
	T last_num = arr.back();
	arr.pop_back();
	return last_num + sum(arr);
}

int main()
{
	vector<int> arr_int = {1, 2, 3, 4};
	vector<float> arr_float = {0.1, 0.2, 0.3, 0.4, 0.5};
	
	cout << "Sum ints:" << sum(arr_int) << endl;
	cout << "Sum floats:" << sum(arr_float) << endl;
	return 0;
}

例题四、递归计数

详细C++代码如下:

#include<iostream>
#include<vector>

using namespace std;

template<typename T>
int count(vector<T> arr){
	if(arr.empty())
		return 0;
	arr.pop_back();
	return count(arr) + 1;
}

int main()
{
	vector<int> array = {0, 1, 2, 3, 4, 5};
	cout << count(array) << endl;
	return 0;
}

例题五、递归求最大值

详细C++代码如下:

#include<iostream>
#include<vector>
#include<stdexcept>

using namespace std;

template<typename T>
T max(vector<T> arr){
	if(arr.empty())
		throw invalid_argument("Cannot select max value from empty sequence.");
	if(arr.size() == 1)
		return arr.at(0);
	
	T back = arr.back();
	arr.pop_back();
	
	T sub_max = max(arr);
	return back > sub_max ? back : sub_max; 
}

int main()
{
	vector<int> array = {1, 5, 10, 25, 16, 1};
	cout << max(array) << endl;
	
	vector<int> negative_array = {-1, -5, -10, -25, -16};
	cout << max(negative_array) << endl;
	return 0; 
}

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值