关于递归和循环的使用(C语言版)

递归是数据结构里常见的,递归调用是通过内存的栈实现的,在调用函数时,系统会将被调函数所需的程序空间安排在一个栈中。每当调用一个函数时,就在栈顶为它分配一个存储区。每当从一个函数退出时就释放它的存储区,栈是采用先进后出(后进先出),当递归不断调用自己,最先调用的先入栈,后面依次调用的函数依次进入栈,最先入栈的位于栈底,最后入栈的栈顶,比如我们穿衣服,最先穿的内衣位于最里面,最后穿的外套位于最外面,脱衣服的最先脱外套,然后依次脱里面的,直至脱光。整个递归调用过程就是一次穿衣脱衣(入栈出栈)的过程。由于递归调用要有大量的函数调用,这也有许多额外的时间开销。函数调用要发送实参,要为被调函数分配存储空间,还要保存返回的值。如果递归调用次数多,导致系统开销太大。这个时候递归就不是好的选择,我们尽量采用循环来实现。
我们来看个例子:斐波那契数列,每一个数值都是其前两个数值之和
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
我们对比递归和循环看看效率
递归:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_FBNC 30

long iFibonacci;
long fibonacci(int num)
{
	iFibonacci++;
	int iResult;
	if(num < 0)
		return -1;	
	if(num == 0){
		return 0;
	}else if(num == 1){
		return 1;
	}
	else{
		return fibonacci(num-1)+fibonacci(num-2);
	}
}

int main(int argc,char *argv[])
{
	for(int i=0;i<=MAX_FBNC;i++){
		iFibonacci = 0;
		printf("%d的Fibonacci:[%ld]\n",i,fibonacci(i));
		printf("调用次数:[%d]\n\n",iFibonacci);
	}
}

运行结果:
在这里插入图片描述
我们发现到第30个数时,函数被调用了2692537次,造成了巨大的资源浪费。

循环:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_FBNC 40

long fibonacci_loop(int num)
{
	int iResult=0;
	int *a=malloc(sizeof(int)*num);
	for(int i=0;i<num;i++){
		if(i==0)
			a[i]=0;
		else if(i==1)
			a[i]=1;
		else
			a[i]=a[i-1]+a[i-2];
	}
	iResult = a[num-1];
	free(a);
	return iResult;
}

int main(int argc,char *argv[])
{
	for(int i=0;i<=MAX_FBNC;i++){
		printf("%d的fibonacci_loop:[%ld]\n",i,fibonacci_loop(i+1));
	}
}

每次计算只调用一次函数,资源开销大大减小,时间复杂度为O(n),效率大大提高。
既然递归的效率远远不如循环,能用循环就用循环,虽然递归的程序非常便于理解。在一些递归调用次数少,便于理解的情况下,可以用递归。例如十进制转换成二进制、十六进制、八进制:

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

char hex_char(int num);

void binary(int num)
{
	int yushu;
	yushu = num%2;
	if(num>=2)
		binary(num/2);
	printf("%d",yushu);
}

void hex(int num)
{
	int yushu;
	yushu = num%16;
	if(num>=16)
		binary(num/16);
	printf("%c",hex_char(yushu));
}

void octonary(int num)
{
	int yushu;
	yushu = num%8;
	if(num>=8)
		octonary(num/8);
	printf("%d",yushu);
}

char hex_char(int num)
{
	char cRusult;
	switch(num){
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:
		case 9:		cRusult=num+0x30;	break;
		case 10:	cRusult='A';		break;
		case 11:	cRusult='B';		break;
		case 12:	cRusult='C';		break;
		case 13:	cRusult='D';		break;
		case 14:	cRusult='E';		break;
		case 15:	cRusult='F';		break;			
	}
	return cRusult;
}

int main(int argc,char *argv[])
{
	int a = 29;
	printf("a:[%d]\n",a);
	printf("binary num is:");
	binary(a);
	fflush(stdout);
	printf("\n");
	
	printf("hex num is:");
	hex(a);
	fflush(stdout);
	printf("\n");

	printf("octonary num is:");
	octonary(a);
	fflush(stdout);
	printf("\n");	
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kaixian2003

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值