超星高级语言程序设计实验作业
实验06 递归程序设计
注:以下内容仅供交流,代码都是本人自己写的,还请同学们先自己编写再进行交流。
1.排列组合
问题描述:编写程序求函数C(m,n)的值。
输入:从键盘随机输入一个自然数和一个非负整数,分别作为m和n的值(m≥n)。
输出:函数C(m,n)的值。
样例1:
输入:4 1
输出:4
样例2:
输入:6 2
输出:15
#include<stdio.h>
//递归函数部分
int math(int m,int n) {
if (n < 0) return 0;
else if (n == 0) return 1;
else if (n == 1) return m;
else if (m < 2 * n) return math(m, m - n);
else if (m >= 2 * n) return math(m - 1, n - 1) + math(m - 1, n);
}
//主函数
int main() {
int m, n;
scanf_s("%d%d", &m, &n);
printf("%d", math(m, n));
return 0;
}
这个题挺简单,按公式来就行。
2.Hermite多项式
题目描述:编写程序,用递归方法求解Hermite 多项式值。Hermite 多项式定义如下。
输入:从键盘随机输入一个非负整数和一个实数,作为n和x的值。
输出:Hn(x)的值,精确到小数点后2位。
样例1:
输入:0 1.5
输出:1.00
样例2:
输入:2 2.4
输出:21.04
#include<stdio.h>
//多项式函数部分
double H(double x,int n) {
if (n == 0) return 1;
else if (n == 1) return 2 * x;
else return 2 * x * H(x, n - 1) - 2 * (n - 1) * H(x, n - 2);
}
//主函数部分
int main() {
int n;
double x;
scanf_s("%d%lf", &n, &x);
printf("%.2lf", H(x, n));
return 0;
}
按公式来就好😁
3.Ackerman函数
问题描述:编写程序,计算 Ackerman 函数值。Ackerman 函数定义如下
输入:从键盘随机输入两个非负整数,分别作为m和n的值。
输出:Ack(m, n)的值。
样例1:输入 2 3 输出 9
样例2:输入 3 2 输出 29
样例3:输入 0 3 输出 4
#include<stdio.h>
int Ack(int m,int n) {
if (m == 0) return n + 1;
if (n == 0) return Ack(m - 1, 1);
if (m > 0 && n > 0)
return Ack(m - 1, Ack(m, n - 1));
}
int main() {
int n,m;
scanf_s("%d%d", &m, &n);
printf("%d", Ack(m, n));
return 0;
}
还是按公式来,注意要看清公式。
4.最大公因数
题目描述:编写程序,用递归方法求解m、n最大公约数。对正整数u和v 可以采用欧几里德辗转相除算法求它们的最大公因数,具体过程如下:
u% v → r1
v % r1 → r2
r1% r2 → r3
r2 % r3 → r4
… …
rn-1% rn → rn+1=0
当余数rn+1=0时,计算过程结束,rn 为正整数u 、v的最大公因数。
输入:从键盘随机输入两个正整数m和n。输出:最大公因数。
样例1:
输入:12 15
输出:3
样例2:
输入:28 49
输出:7
#include<stdio.h>
int C(int u,int v) {
int r;
//返回情况,进入函数时因为上步中传入的为u%v故此时的u可能为零,则v即为所求
if (u==0) return v;
//使u一直是较大的数,减少取余运算次数
if (u < v) {
r = u; u = v; v = r;
}
//当未从上面返回时,说明辗转相除未结束 较大数%较小数与较小数一起再进入函数
return C(u % v, v);
}
int main() {
int n,m;
scanf_s("%d%d", &m, &n);
printf("%d", C(m, n));
return 0;
}
5.顺序检索
题目描述:编写程序,用递归方法在整数组中进行顺序检索。
输入:
第一行输入一个正整数n(0<n≤100),表示数组的元素个数;
第二行依次输入n个整数,作为数组的元素;
第三行输入待检索的关键字。
输出:
如果数组中含有关键字,则输出其首次出现的位置(下标值较小的位置)否则输出NULL。
样例1:
输入:
8
0 2 3 4 5 9 10 8
3
输出:
2
样例2:
输入:
8
0 2 3 4 5 9 10 8
6
输出:
NULL
#include<stdio.h>
// 递归函数部分,p指向储存第二行数字的数组首地址,key关键字,n数组长度,i记录首次出现位置
int C(int*p,int key,int n,int i) {
if (i == n) return -1;//当进入时i为n说明前n项未出现关键值,即无结果返回-1
if (*(p + i) == key) return i;//出现时返回当前位置
else return C(p, key, n, i + 1);//未出现时进行下一项的判断
}
int main() {
int n,a[100],key,i;
scanf_s("%d", &n);
for ( i = 0; i < n; i++)
scanf_s("%d", &a[i]);
scanf_s("%d", &key);
key = C(a, key, n, 0);//用key再储存返回值,若为-1说明未找到,其他情况key即为下标值
if (key == -1) printf("NULL");
else printf("%d",key);
return 0;
}
6.最大元素
题目描述:编写程序,用递归方法求解长度为n的整型数组中最大元素值。
输入:第一行输入一个正整数n(0<n≤100),表示数组的元素个数;第二行依次输入n个整数,作为数组的元素。
输出:最大元素的值。
样例1:
输入:
10
9 8 7 6 5 4 3 2 1 0
输出:
9
样例2:
输入:
10
0 1 2 3 4 5 6 7 8 9
输出:
9
#include<stdio.h>
//递归函数部分,r用于储存最大值,i记录当前比较项数
int max(int*p,int n,int r,int i) {
//当i=n时比较结束,返回r
if (i == n) return r;
//比较r与当前项大小,将较大值赋给r
if (r < *(p + i)) r = *(p + i);
return max(p, n, r, i + 1);
}
int main() {
int n,a[100],i;
scanf_s("%d", &n);
for ( i = 0; i < n; i++)
scanf_s("%d", &a[i]);
//函数中传入数组首地址,数组中的项数,开始为r传入a[0]的值,为i传入0
printf("%d", max(a, n, a[0], 0));
return 0;
}
7.数组反序
题目描述:编写程序,用递归方法反序数组。
输入:第一行输入一个正整数n(0<n≤100),表示数组的元素个数;第二行依次输入n个整数,作为数组的元素。
输出:顺次输出逆序后数组中元素,元素间以一个西文空格间隔,最后一个元素后无字符。
样例1:
输入:
8
0 2 3 4 5 9 10 8
输出:
8 10 9 5 4 3 2 0
样例2:
输入:
5
0 2 3 3 5
输出:
5 3 3 2 0
#include<stdio.h>
//递归函数部分,用于交换数组中值实现逆序
//其中开始时n直接赋值元素数减一即最后一个元素的下标,i记录当前交换项
void L(int*p,int n,int i) {
int r;
//交换对应需要逆序交换项的值
r = *(p + i);
*(p + i) = *(p + n - i);
*(p + n - i) = r;
//当i为n/2时,逆序完成结束递归
if (i == n/2) return;
L(p, n, i + 1);
}
int main() {
int n,a[100],i;
scanf_s("%d", &n);
for ( i = 0; i < n; i++)
scanf_s("%d", &a[i]);
//调用函数实现逆序,直接传递最后一个元素的下标值,便于交换时指针的计算
L(a, n-1, 0);
for (i = 0; i < n; i++) {
printf("%d", a[i]);
if (i != n - 1)printf(" ");
}
return 0;
}
8.截木条
题目描述:
给定一个长度为n的木条,将其在大致2/5的位置截断,得到2个长度仍为整数的木条;如果新得到的木条的长度仍旧超过规定长度k,将继续按照上述方法处理得到的木条,直到所有木条的长度都不大于k。
编写程序,用递归方法计算一个长度为n的木条,当规定长度为k时,其经过上述截断过程会得到多少根木条。其中:n、k均为正整数,n>10,k>3,且假设木条截断所得短木条长度四舍五入为正整数,长木条长度为总长减去短木条长度。
输入:顺次从键盘输入两个正整数n和k(n>10,k>3)。
输出:木条根数。
样例1:
输入: 20 4
输出: 7
样例2:
输入: 3 20
输出: 1
#include<stdio.h>
//定义i储存木条个数
int i=1;
//递归函数部分
void L(int n,int k) {
int n1=0, n2=0;
//当n比k大时将n分割,这时木条数加一
if(n>k){
n1 = n * 2 / 5;
n2 = n - n1;
i++;
}
if (n1 > k) L(n1, k);
if (n2 > k) L(n2, k);
}
//主函数
int main() {
int n,k;
scanf_s("%d%d", &n,&k);
if (n <= k);
else L(n, k);
printf("%d", i);
return 0;
}
这个为了省事,直接用了全局变量😁
其他方法大家自行摸索吧