没有合适的资源?快使用搜索试试~ 我知道了~
首页c语言经典算法 C语言 算法
资源详情
资源评论
资源推荐

二、算法设计的方法
1.递推法
递推法是利用问题本身所具有的一种递推关系求问题解的一种方法。设要求问题规模为 N
的解,当 N=1 时,解或为已知,或能非常方便地得到解。能采用递推法构造算法的问题有
重要的递推性质,即当得到问题规模为 i-1 的解后,由问题的递推性质,能从已求得的规模
为 1,2,…,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。细节见以下程序。
# include <stdio.h>
# include <malloc.h>
# define MAXN 1000
void pnext(int a[ ],int k){
int *b,m=a[0],i,j,r,carry;
b=(int * ) malloc(sizeof(int)* (m+1));
for ( i=1;i<=m;i++) b[i]=a[i];

for ( j=1;j<=k;j++){
for ( carry=0,i=1;i<=m;i++){
r=(i<a[0]?a[i]+b[i]:a[i])+carry;
a[i]=r%10;
carry=r/10;
}
if (carry) a[++m]=carry;
}
free(b);
a[0]=m;
}
void write(int *a,int k){
int i;
printf(“%4d!=”,k);
for (i=a[0];i>0;i--)
printf(“%d”,a[i]);
printf(“\n\n”);
}
void main(){
int a[MAXN],n,k;
printf(“Enter the number n: “);
scanf(“%d”,&n);
a[0]=1;

a[1]=1;
write(a,1);
for (k=2;k<=n;k++){
pnext(a,k);
write(a,k);
getchar();
}
}
2.递归
递归是设计和描述算法的一种有力的工具,由于它在复杂算法的描述中被经常采用,为此
在进一步介绍其他算法设计方法之前先讨论它。
能采用递归描述的算法通常有这样的特征:为求解规模为 N 的问题,设法将它分解成规模
较小的问题,然后从这些小问题的解方便地构造出大问题的解,并且这些规模较小的问题
也能采用同样的分解和综合方法,分解成规模更小的问题,并从这些更小问题的解构造出
规模较大问题的解。特别地,当规模 N=1 时,能直接得解。
【问题】 编写计算斐波那契(Fibonacci)数列的第 n 项函数 fib(n)。
斐波那契数列为:0、1、1、2、3、……,即:
fib(0)=0;
fib(1)=1;
fib(n)=fib(n-1)+fib(n-2) (当 n>1 时)。
写成递归函数有:
int fib(int n){
if (n==0) return 0;
if (n==1) return 1;
if (n>1) return fib(n-1)+fib(n-2);

}
递归算法的执行过程分递推和回归两个阶段。在递推阶段,把较复杂的问题(规模为 n)
的求解推到比原问题简单一些的问题(规模小于 n)的求解。例如上例中,求解 fib(n),把
它推到求解 fib(n-1)和 fib(n-2)。也就是说,为计算 fib(n),必须先计算 fib(n-1)和 fib(n-2),
而计算 fib(n-1)和 fib(n-2),又必须先计算 fib(n-3)和 fib(n-4)。依次类推,直至计算 fib(1)和
fib(0),分别能立即得到结果 1 和 0。在递推阶段,必须要有终止递归的情况。例如在函数
fib 中,当 n 为 1 和 0 的情况。
在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解,例如得到
fib(1)和 fib(0)后,返回得到 fib(2)的结果,……,在得到了 fib(n-1)和 fib(n-2)的结果后,返
回得到 fib(n)的结果。
在编写递归函数时要注意,函数中的局部变量和参数知识局限于当前调用层,当递推进入
“简单问题”层时,原来层次上的参数和局部变量便被隐蔽起来。在一系列“简单问题”层,
它们各有自己的参数和局部变量。
由于递归引起一系列的函数调用,并且可能会有一系列的重复计算,递归算法的执行效率
相对较低。当某个递归算法能较方便地转换成递推算法时,通常按递推算法编写程序。例
如上例计算斐波那契数列的第 n 项的函数 fib(n)应采用递推算法,即从斐波那契数列的前两
项出发,逐次由前两项计算出下一项,直至计算出要求的第 n 项。
【问题】 组合问题
问题描述:找出从自然数 1、2、……、n 中任取 r 个数的所有组合。例如 n=5,r=3 的所有
组合为: (1)5、4、3 (2)5、4、2 (3)5、4、1
(4)5、3、2 (5)5、3、1 (6)5、2、1
(7)4、3、2 (8)4、3、1 (9)4、2、1
(10)3、2、1
分析所列的 10 个组合,可以采用这样的递归思想来考虑求组合函数的算法。设函数为 void
comb(int m,int k)为找出从自然数 1、2、……、m 中任取 k 个数的所有组合。当组合的第一
个数字选定时,其后的数字是从余下的 m-1 个数中取 k-1 数的组合。这就将求 m 个数中取
k 个数的组合问题转化成求 m-1 个数中取 k-1 个数的组合问题。设函数引入工作数组 a[ ]存
放求出的组合的数字,约定函数将确定的 k 个数字组合的第一个数字放在 a[k]中,当一个
组合求出后,才将 a[ ]中的一个组合输出。第一个数可以是 m、m-1、……、k,函数将确
定组合的第一个数字放入数组后,有两种可能的选择,因还未去顶组合的其余元素,继续
递归去确定;或因已确定了组合的全部元素,输出这个组合。细节见以下程序中的函数
comb。
【程序】
剩余17页未读,继续阅读















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0