C语言经典算法解析

<h2><strong>[程序1] 题目:输入三个整数x,y,z,请把这三个数由小到大输出。</strong></h2> 程序分析:我们想办法把最小的数赋值给x,先将x与y进行比较,如果x〉y则将x与y的值进行交换, 然后再用x与z进行比较,如果x〉z则将x与z的值进行交换,这样能使x最小。 程序源码: #include<stdio.h> main() { int x,y,z,t; sca

[程序1] 题目:输入三个整数x,y,z,请把这三个数由小到大输出。

程序分析:我们想办法把最小的数赋值给x,先将x与y进行比较,如果x〉y则将x与y的值进行交换, 然后再用x与z进行比较,如果x〉z则将x与z的值进行交换,这样能使x最小。 程序源码: #include main() { int x,y,z,t; scanf(“%d%d%d“,&x,&y,&z); if (x〉y) {t=x;x=y;y=t;} /*交换x,y的值*/ if(x〉z) {t=z;z=x;x=t;} /*交换x,z的值*/ if(y〉z) {t=y;y=z;z=t;} /*交换z,y的值*/ printf(“small to big: %d %d %d\n“,x,y,z); } 举一反三:读者可以自行写出4个数的情况。

[程序2]题目:输出九九乘法表

程序分析:在这道题目中,显然,我们应该使用循环结构。我们知道,乘法是两个元素的运算,我们可以定义两个变量i,j,然后让i的值从1变化到9,j的值从1变化到9,组成81个乘法算式。 程序源码: #include voidmain() { inti,j; for(i=1;i<=9;i++)     /*外循环控制变量i,控制被乘数变化*/ {for(j=1;j<=9;j++)   /*内循环控制变量j,控制乘数变化*/ printf(“%d*%d=%-4d”,i,j,i*j); /*表示输出结果左对齐,占4位*/ printf(“\n”);        /*换行*/ } } 本题考查点:for循环语句的使用和表达,循环嵌套 举一反三:请读者自行用循环结构输出“九九加法表”

[程序3]题目:判断101-200之间有多少个素数,并输出所有素数。

程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数)【这个数的平方根】,如果能被整除,则表明此数不是素数,反之是素数。这是判断一个数是否为素数的办法,那么如果判断101-200之间的素数,则需要使用循环结构。 程序源码: #include #include  /*因为下面的代码中使用了sqrt()函数,所以在这里要声明math.h头文件*/ intm,i,k,h=0,leap=1; /*定义整型变量,并且定义了标记leap,并使leap的初始值为1*/ printf(“\n“); for(m=101;m〈=200;m++) { k=sqrt(m+1); for(i=2;i〈=k;i++) if(m%i==0) {leap=0;break;} if(leap)                     /*将“leap”作为标记用,当它为非0时执行下面的语句*/ {printf(“%-4d“,m);h++; if(h%10==0) printf(“\n“); } leap=1; } printf(“\nThe total is %d“,h); } 本题的考点是:判断一个数是否为素数的算法,还有循环结构。 举一反三:请读者自行用循环结构输出2000年以来的闰年。

[程序4]题目:输入两个正整数m和n,求其最大公约数和最小公倍数。

程序分析:利用辗转相除法来完成这个题目。辗转相除法,又称欧几里得算法,是求最大公约数的算法。辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的相除余数的最大公约数。例如,252和105的最大公约数是21(252 = 21 × 12;105 = 21 × 5);因为252 − 105 = 147,所以147和105的最大公约数也是21。在这个过程中,较大的数缩小了,所以继续进行同样的计算可以不断缩小这两个数直至其中一个变成零。这时,所剩下的还没有变成零的数就是两数的最大公约数。 程序源码: #include main() { int a,b,num1,num2,temp; printf(“please input two numbers:\n“); scanf(“%d,%d“,&num1,&num2); if(num1) { temp=num1;    /*这三行代码是做数字的交换*/ num1=num2; num2=temp; } a=num1;b=num2; while(b!=0)        /*利用辗除法,直到b为0为止*/ { temp=a%b; a=b; b=temp; } printf(“gongyueshu:%d\n“,a); printf(“gongbeishu:%d\n“,num1*num2/a); } 本题考点:最大公约数和最小公倍数的算法。循环结构。 举一反三:请读者自行求出14,37的最大公约数和最小公倍数,然后上机运行程序,对比结果。

[程序5]题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。

程序分析:我们可以看出,这个数列中,前一项分数的分子与分母之和,等于后一项分数的分子;前一项分数的分子,是后一项分数的分母。利用循环结构,可以把这道题解出来。 程序源码: #include main() { int n,t,number=20;  /*定义整形变量n,t,使变量number初始值为20*/ float a=2,b=1,s=0;  /*定义浮点型变量*/ for(n=1;n〈=number;n++) { s=s+a/b; t=a;a=a+b;b=t;    /*这部分是程序的关键,请读者根据程序分析猜猜t的作用*/ } printf(“sum is %9.6f\n“,s); } 本题考点:循环结构的基本使用方法,对题目规律的分析。 举一反三:请读者自行写出求1!+2!+……+20!的程序代码,并上机调试。

 [程序6]题目:求一个3*3矩阵对角线元素之和

程序分析:利用双重for循环控制输入二维数组,再将a[i][i]累加后输出。 程序源码: #include main() { floata[3][3],sum=0;     /*定义二维数组a,并且数组中存放的数据为浮点型数据*/ int i,j; printf(“pleaseinput rectangle element:\n“); for(i=0;i〈3;i++)  /*外循环控制行*/ {for(j=0;j〈3;j++)  /*内循环控制列*/ scanf(“%f“,&a[i][j]);     /*这部分的含义是把矩阵输入计算机*/ } for(i=0;i〈3;i++) sum=sum+a[i][i];  /*这部分是对对角线元素求和,对角线元素行标和列标都一样*/ printf(“duijiaoxianhe is %6.2f“,sum); } 本题考查循环结构和数组的基本使用。 举一反三:请读者自行写出代码:求一个矩阵的转置。

[程序7] 题目:将一个数组逆序输出。

程序分析:用数组里的第一个数与最后一个数交换。 程序源码: #include #define N 5    /*定义符号常量N为5*/ main() { int a[N]={9,6,5,4,1},i,temp; printf(“original array:\n“); for(i=0;i〈N;i++) printf(“%4d“,a[i]); for(i=0;i〈N/2;i++) { temp=a[i];    /*这几行代码的作用就是将数组里的第一个数与最后一个数交换*/ a[i]=a[N-i-1]; a[N-i-1]=temp; } printf(“sorted array:\n“); for(i=0;i〈N;i++) printf(“%4d“,a[i]); } 本题使用了符号常量,并且使用了#define N 5的预处理命令,这个命令的含义是:在程序执行之前将 代码中的所有N替换为5。

[程序8] 题目:打印出杨辉三角形

程序分析:杨辉三角的规律:1.每行数字左右对称,由1开始逐渐变大,然后变小,回到1。2、第n行的数字个数为n个。3、第n行数字和为2^(n-1)。(2的(n-1)次方)4、每个数字等于上一行的左右两个数字之和。本题使用数组的方法进行输出。 程序源码: #include main() {int i,j; int a[10][10]; printf(“\n“); for(i=0;i〈10;i++) {a[i][0]=1;  /*每行开始的第一个数字为1*/ a[i][i]=1;} /*每行结束的最后一个数字为1*/ for(i=2;i〈10;i++) for(j=1;j〈i;j++) a[i][j]=a[i-1][j-1]+a[i-1][j]; for(i=0;i〈10;i++) {for(j=0;j〈=i;j++) printf(“%5d“,a[i][j]); printf(“\n“); } } 本题考查杨辉三角的算法,数组的基本使用。 举一反三:题目中输出的是杨辉三角的前十行,请读者自行更改代码,实现如下功能:用户输入数字为多少,就输出多少行杨辉三角。

[程序9]题目:输出斐波那契数列的前20项,每行5个数据。

程序分析:斐波那契数列为1,1,2,3,5,8,……,通过观察可以发现,前两项数据为1,从第三项开始,数据为前两项之和。 程序源码: #include main() { int fab[20]={1,1},n; for(n=2;n<20;n++) fab[n]=fab[n-1]+fab[n-2]; for(n=0;n<20;n++) { if(n%5==0) printf(“\n”); /*题目要求每行5个数*/ printf(“%12d”,fab[n]); } } 本题考查斐波那契数列的算法,以及数组和循环结构。但是本题特别要注意的一点是: 笔者经过测试,如果按照代码改为输出40个,则这样输出的斐波那契数列中存在负数。 这是怎么回事呢?我们回头看一下程序代码,我们定义的都是整型数据,但是到30个的时候已经超过了整 型数据的范围,出现了数据溢出。 举一反三:请各位读者自行完善程序,要求输出斐波那契数列前30项。

[程序10]题目:输入30个学生的成绩,求出各个分数段之间的人数,成绩的最高分,最低分,平均分。

程序分析:本题使用数组完成最为简单。因为数组可以批量处理数据,使程序更加简洁明快。所有分析将在程序代码的注释中写出。 程序源码: #include main() { int i,a[30],max,min,ave=0;    /*定义数组a,包括30个数据*/ int b[5]={0};           /*定义数组b,并且使数组中第一个数为0,这个数组用来记5个分数段人数*/ printf("30 students goals:\n"); for(i=1;i<30;i++) scanf("%d",&a[i]);    /*输入30个学生的成绩*/ max=min=a[0];         /*使最大值和最小值初始化为数组a的第一个数值*/ for(i=1;i<30;i++) { if(a[i]>=0&&a[i]<=59)b[0]++;  /*前五行代码表示统计个分数段人数*/ if(a[i]>=60&&a[i]<=69)b[1]++; if(a[i]>=70&&a[i]<=79)b[2]++; if(a[i]>=80&&a[i]<=89)b[3]++; if(a[i]>=90&&a[i]<=100)b[4]++; if(a[i]>max)max=a[i];   /*这两行表示将最大值和最小值找出*/ if(a[i][程序11]题目:比较输入的三个字符串的大小 程序分析:本题主要账务比较字符串大小的原理。按照英语字母排列顺序,先比较第一个字母,然后依次 比较下去。 程序源码: #include #include  /*因为下面的程序中使用了比较字符串大小函数,在这里声明。*/ main() { char string[20]; char str[3][20]; int i; printf("Please input 3 strings:\n"); for(i=0;i<3;i++) gets(str[i]); if(strcmp(str[0],str[1])>0) strcpy(string,str[0]); else strcpy(string,str[1]); if(strcmp(str[2],string)>0) strcpy(string,str[2]); printf("Thelargest string is:\n%s\n",string); } 请读者自行为本程序代码写出注释。 本题所用字符串处理函数请参阅谭浩强的《C程序设计》第157页。

[程序12]题目:小明有五本新书,要借给A,B,C三位小朋友,若每人每次只能借一本,则可以有多少种不同的借法?

问题分析与算法设计 本问题实际上是一个排列问题,即求从5个中取3个进行排列的方法的总数。首先对五本书从1至5进行编号,然后使用穷举的方法。假设三个人分别借这五本书中的一本,当三个人所借的书的编号都不相同时,就是满足题意的一种借阅方法。 *程序说明与注释 int main() { int a,b,c,count=0; printf("There are diffrent methods for XM to distribute books to 3readers:\n"); for(a=1;a<=5;a++)  /*穷举第一个人借5本书中的1本的全部情况*/ for(b=1;b<=5;b++) /*穷举第二个人借5本书中的一本的全部情况*/ for(c=1;a!=b&&c<=5;c++) /*当前两个人借不同的书时,穷举第三个人借5本书 中的1本的全部情况*/ if(c!=a&&c!=b) /*判断第三人与前两个人借的书是否不同*/ printf(count%8?"%2d:%d,%d,%d ":"%2d:%d,%d,%d\n",++count,a,b,c); /*打印可能的借阅方法*/ } *运行结果 There are diffrent methods for XM to distribute books to 3 readers: 1: 1,2,3 2: 1,2,4 3: 1,2,5 4: 1,3,2 5: 1,3,4 6: 1,3,5 7: 1,4,2 8: 1,4,3 9: 1,4,5 10:1,5,2 11:1,5,3 12:1,5,4 13:2,1,3 14:2,1,4 15:2,1,5 16:2,3,1 17:2,3,4 18:2,3,5 19:2,4,1 20:2,4,3 21:2,4,5 22:2,5,1 23:2,5,3 24:2,5,4 25:3,1,2 26:3,1,4 27:3,1,5 28:3,2,1 29:3,2,4 30:3,2,5 31:3,4,1 32:3,4,2 33:3,4,5 34:3,5,1 35:3,5,2 36:3,5,4 37:4,1,2 38:4,1,3 39:4,1,5 40:4,2,1 41:4,2,3 42:4,2,5 43:4,3,1 44:4,3,2 45:4,3,5 46:4,5,1 47:4,5,2 48:4,5,3 49:5,1,2 50:5,1,3 51:5,1,4 52:5,2,1 53:5,2,3 54:5,2,4 55:5,3,1 56:5,3,2 57:5,3,4 58:5,4,1 59:5,4,2 60:5,4,3 [程序13]假设银行一年整存零取的月息为0.63%。现在某人手中有一笔钱,他打算在今后的五年中的年底取出1000元,到第五年时刚好取完,请算出他存钱时应存入多少。 *问题分析与算法设计 分析存钱和取钱的过程,可以采用倒推的方法。若第五年年底连本带息要取1000元,则要先求出第五年年初银行存款的钱数: 第五年初存款=1000/(1+12*0.0063) 依次类推可以求出第四年、第三年……的年初银行存款的钱数: 第四年年初存款=(第五年年初存款+1000)/(1+12*0.0063) 第三年年初存款=(第四年年初存款+1000)/(1+12*0.0063) 第二年年初存款=(第三年年初存款+1000)/(1+12*0.0063) 第一年年初存款=(第二年年初存款+1000)/(1+12*0.0063) 通过以上过程就可以很容易地求出第一年年初要存入多少钱。 *程序说明与注释 #include int main() { int i; float total=0; for(i=0;i<5;i++) /*i 为年数,取值为0~4年*/ total=(total+1000)/(1+0.0063*12); /*累计算出年初存款数额,第五次的计算 结果即为题解*/ printf("He must save %.2fat first.\n",total); } *运行结果 He must save 4039.44 at first

[程序14]谁在说谎

张三说李四在说谎,李四说王五在说谎,王五说张三和李四都在说谎。现在问:这三人中到底谁说的是真话,谁说的是假话? *问题分析与算法设计 分析题目,每个人都有可能说的是真话,也有可能说的是假话,这样就需要对每个人所说的话进行分别判断。假设三个人所说的话的真假用变量A、B、C表示,等于1表示该人说的是真话; 表示这个人说的是假话。由题目可以得到: *张三说李四在说谎 张三说的是真话:a==1&&b==0 或 张三说的是假话:a==0&&b==1 *李四说王五在说谎 李四说的是真话:b==1&&c==0 或 李四说的是假话:b==0&&c==1 *王五说张三和李四都在说谎 王五说的是真话:c==1&&a+b==0 或 王五说的是假话:c==0&&a+b!=0 上述三个条件之间是“与”的关系。将表达式进行整理就可得到C语言的表达式: (a&&!b||!a&&b)&&(b&&!c||!b&&c)&&(c&&a+b==0||!c&&a+b!=0) 穷举每个人说真话或说假话的各种可能情况,代入上述表达式中进行推理运算,使上述表达式均为“真”的情况就是正确的结果。 *程序说明与注释 #include int main() { int a,b,c; for(a=0;a<=1;a++) for(b=0;b<=1;b++) for(c=0;c<=1;c++) if((a&&!b||!a&&b)&&(b&&!c||!b&&c)&&(c&&a+b==0||!c&&a+b!=0)) { printf("Zhangsan told a %s.\n",a?"truth":"lie"); printf("Lisi told a %s.\n",b?"truch":"lie"); printf("Wangwu told a %s.\n",c?"truch":"lie"); } } *运行结果 Zhangsan told a lie (张三说假话) Lisi told a truch. (李四说真话) Wangwu told a lie. (王五说假话)
LICENSED UNDER CC BY-NC-SA 4.0
Comment