递推法分析
能采用递推法的问题具有如下重要性质:即当得到问题规模为i-1的解后,由问题的递推性质,能构造出问题规模为i的解。这样,程序可以从i=0或i=1出发,重复的,由已知至i-1规模的解,通过递推,获得规模为i的解,直至得到规模为N的解。
例:编写程序,对给定的n(n<=100),计算并输出k的阶乘k!(k=1, 2, ……, n)的全部有效数字。
由于要求的整数可能大大超出一般整数的位数,程序用一维数组存储长整数,存储长整数数组的每一个元素只存储长整数的一位数字。如有m位长整数N用数组a[]存储:
N=a[m]×10m-1+ a[m-1]×10m-2+……+ a[2]×101+ a[1]×100
并用a[0]存储长整数N的位数m,即a[0]=m。按上述约定,数组的每个元素存储k的阶乘k!的一位数字,并从低位到高位依次存于数组的第二元素、第三元素……例如,5!=120,在数组中的存储形式为:
3 | 0 | 2 | 1 | …… |
首元素3表示长整数是一个3位数,接着是低位到高位依次是0、2、1,表示长整数是120.
计算阶乘k!可采用对以求得的阶乘(k-1)!连续累加k-1次后求出。例如,4!=24,计算5!,可对原来的24再累加4次24后得到120.
C语言实现代码:
#include<stdio.h>
#include<malloc.h>
#define MAXN 1000
void recursion(int a[], int k)
{
//已知a中的(k-1)!,求出k!(k<1000)
int * b;
int m=a[0];
b=(int *)malloc(MAXN * sizeof(int));
for(int i=1; i<=m; i++)
{
b[i]=a[i];
}
for(int j=1; j<k; j++)
{
//控制累加k-1次
int carry=0;
int r;
for(int i=1; i<=m; i++)
{
r=a[i]+b[i]+carry;
a[i]=r%10;
carry=r/10;
}
if(carry)
{
m++;
a[m]=carry;
b[m]=0;
}
}
free(b);
a[0]=m;
}
void write(int * a, int k)
{
printf("%4d! = ", k);
for(int i=a[0]; i>0; i--)
{
printf("%d", a[i]);
}
printf("/n");
}
void main()
{
int a[MAXN];
a[0]=1;
a[1]=1;
int n;
printf("Enter the number:");
scanf("%d", &n);
write(a, 1);
for(int k=2; k<=n; k++)
{
recursion(a, k);
write(a, k);
}
}
递推法总结
递推法是一种简单有效的方法,一般用这种方法编写的程序执行效率很高,可以解决具有前效相关性,且前效相关性顺序确定、个数不多、个数为定数的问题。
递推法和递归法的关系:任何可以用递推法解决的问题,都可以很方便的利用递归法解决;但是,并非所有能用递归法解决的问题都能用递推法解决。这是因为,递归法利用的递归工作栈,可以为任意长度和顺序的前效相关性。
程序编译正确,运行过程中出现错误:DAMAGE:after Normal block (#45) at 0x003707AB。在csdn上找到原因:断点调试发现前面都可以通过,只要走到释放内存的free处,程序就会挂掉,后来发现是内存访问越界,针对该程序而言是使用malloc申请的空间过小,编译器傻不拉叽的往前走,读写都可以正确得到结果,直到free的时候编译器才发现问题,于是就崩掉了。
用malloc分配的内存空间,如果越界,free时就会产生这样的错误。今天无意发现了一个牛人的博客,呵呵,高兴!