数据结构学习笔记(11.递归的应用之常用递归算法)

本节知识点:

1.递归的定义:
   a.递归是一种数学上分而自治的思想,递归将大型复杂问题转化成为与原问题相同但规模较小的问题进行处理。
   b.递归函数:即函数自身调用自身的函数。
   c. 递归需要有边界条件:当边界条件不满足时,递归继续进行、当边界条件满足时,递归停止!
   d. 递归需要注意的问题:在递归层数不断增多的过程中,程序栈溢出的风险也在不断增大!!!
2.斐波拉契数列递归解法:
示例代码:
#include <stdio.h>
#include <stdlib.h>


int fibonacci(int n)
{
	if(n > 1)
	{
		return (fibonacci(n-1) + fibonacci(n-2));
	}	
	else if(1 == n)
	{
		return 1;
	}
	else if(0 == n)
	{
		return 0;
	}
} 

int main(int argc, char *argv[])
{
	
	int i = 0;
	for(i = 1; i <= 10; i++)
	{
		printf("fibonacci(%d) = %d\n", i, fibonacci(i));
	}	
	return 0;
}



注意:斐波拉契数列,本身就是一个递归数列,所以可以直接找到递归公式。这个递归算法中,n=1和n=0是递归出口!
3.strlen递归解法:
示例代码:
#include <stdio.h>

int strlen(const char* s)
{
	if(NULL == s)
	{
		return -1;
	}
	if('\0' == *s)
	{
		return 0;
	}
	return (strlen(s+1) + 1);	
}
int main()
{
	printf("%d\n",strlen("12345"));
	printf("%d\n",strlen(NULL));
	printf("%d\n", strlen(""));
	return 0;	
}
注意:其实return 就是一直在每层递归函数中加1而已!
4.递归用于反向输出:
   a. 由于递归函数,一般都是从外到内进入,再依次从内层到外层的弹出,所以很适合处理反向输出的问题!!!
示例代码:
#include <stdio.h>

void reverse(const char* s)
{
	if(NULL != s)
	{
		if('\0' == *s)
		{
			printf("\n");
		}
		else
		{
			reverse(s+1);
			printf("%c",*s);
		} 
	}
}

int main()
{
	reverse("12345");
	printf("\n");
	return 0;
}
5.汉诺塔递归解法:
   a.对于汉诺塔算法来说,这样的递归就有点难度了!首先这里讨论的是三根柱子的汉诺塔,汉诺塔的具体规则是:小的永远在大的上面,一次只能移动一个盘!
   b.算法分析: 对于三根柱子,我们分别叫做,起点、中间变量、目标!我们的目的就是把起点上的n个盘子经过中间变量,移动到目标上去!我们可以将其简化成,将起点上的n-1个盘子移动到中间变量上去,再将起点上的最后一个盘子移动到目标上去,最后将中间变量上的n-1个盘子,移动到目标上去!这样我们的递归模型就建立好了,一直去寻找n-1,值到只有一个盘子的情况时,就直接将起点上的一个盘子移动到目标上去!这个就是递归出口!!!
#include <stdio.h>

/*n表示多少个盘子,a是起点,b是中间变量,c是目标*/ 
void hanoi(int n, char a, char b, char c)
{
	if(1 == n)//如果是一个盘子的时候,就直接从起点移动到目标 
	{
		printf("%c -> %c\n",a,c);
	} 
	else
	{
		hanoi(n-1, a, c, b); //先将n-1个盘子从起点a经过目标c移动到中间变量b上去 
		
		printf("%c -> %c\n",a,c);  //将第n个盘子从a移动到c上去 
	
		hanoi(n-1, b, a, c);  //再将中间变量上b的n-1个盘子经过a移动到c上去 
	} 
}
int main()
{
	hanoi(3,'a','b','c'); 
	return 0;
}
注意:这里面值得考虑清楚的是,其实每次所谓的起点、中间变量、目标 这些概念都是相对的!!!
6.全排列问题的递归解法:
示例代码:
#include <stdio.h>

/*s为需要全排列的字符串  a为字符串起始下标   b为字符串终止下标*/
void permutation(char* s, int a, int b)
{
	int i = 0; 
	if((NULL != s) && (b >= a) && (a >= 0))
	{
		if(a == b)
		{
			printf("%s\n",s);
		}
		else
		{
			for(i = a; i <= b; i++)
			{
				char c = s[i];
				s[i] = s[a];
				s[a] = c;
				
				permutation(s, a+1, b);
				
				char d = s[i]; //把破坏的字符串  还原回去 
				s[i] = s[a];
				s[a] = d;
				
				
			} 
		} 

	} 
}

int main()
{
	char s[] = "abcde";
    
    permutation(s, 0, 4);
	return 0;
}
注意:这个程序是这样的,abcde   abced这是最内层的递归函数,abdce   abdec   abedc   abecd 这是倒数第二层的递归函数,依次类推!其实就是一个for循环和递归函数的嵌套!值得注意的是,这个函数仅仅能解决字符串中没有相同字符情况的全排列问题,如果有相同字符,就会出现重复的情况!!!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值