
c语言算法
果蔗-平行线的判定
2023年2月22日发(作者:海豚肉)C语言常用算法一、基本算法1.交换(两量交换借助第三者)
例1、任意读入两个整数,将二者的值交换后输出。main()
{inta,b,t;scanf("%d%d",&a,&b);printf("%d,%dn",a,b);t=a;
a=b;b=t;printf("%d,%dn",a,b);}【解析】程序中加粗部分为算
法的核心,如同交换两个杯子里的饮料,必须借助第三个空杯
子。假设输入的值分别为3、7,则第一行输出为3,7;第二
行输出为7,3。其中t为中间变量,起到“空杯子”的作用。注
意:三句赋值语句赋值号左右的各量之间的关系!【应用】例
2、任意读入三个整数,然后按从小到大的顺序输出。main()
{inta,b,c,t;scanf("%d%d%d",&a,&b,&c);/*以下两个if语句使
得a中存放的数最小*/if(a>b){t=a;a=b;b=t;}if(a>c){t=a;a=c;
c=t;}/*以下if语句使得b中存放的数次小*/if(b>c){t=b;b=c;
c=t;}printf("%d,%d,%dn",a,b,c);}2.累加ss+累加算法的要领
是形如“=A”的累加式,此式必须出现在循环中才能被反复执行,
从而实现累加功能。“A”通常是有规律变化的表达式,s在进入
循环前必须获得合适的初值,通常为0。例1、求
1+2+3+„„+100的和。main(){inti,s;s=0;i=1;while(i<=100)
{s=s+i;/*累加式*/i=i+1;/*特殊的累加式*/}
printf("1+2+3+...+100=%dn",s);}【解析】程序中加粗部分为累
加式的典型形式,赋值号左右都出现的变量称为累加器,其中
“i=i+1”为特殊的累加式,每次累加的值为1,这样的累加器又
称为计数器。
C语言常用算法3.累乘累乘算法的要领是形如“s=s*A”的累乘
式,此式必须出现在循环中才能被反复执行,从而实现累乘功
能。“A”通常是有规律变化的表达式,s在进入循环前必须获得
合适的初值,通常为1。例1、求10![分析]10!
=1×2×3ׄ„×10main(){inti;longc;c=1;i=1;while(i<=10)
{c=c*i;/*累乘式*/i=i+1;}printf("1*2*3*...*10=%ldn",c);}
二、非数值计算常用经典算法1.穷举也称为“枚举法”,即将
可能出现的每一种情况一一测试,判断是否满足条件,一般采
用循环来实现。例1、用穷举法输出所有的水仙花数(即这样
的三位正整数:其每位数位上的数字的立方和与该数333相等,
比如:1+5+3=153)。[法一]main(){intx,g,s,b;
for(x=100;x<=999;x++){g=x%10;s=x/10%10;b=x/100;
if(b*b*b+s*s*s+g*g*g==x)printf("%dn",x);}}【解析】此方法是
将100到999所有的三位正整数一一考察,即将每一个三位正
整数的个位数、十位数、百位数一一求出(各数位上的数字的
提取算法见下面的“数字处理”),算出三者的立方和,一旦与原
数相等就输出。共考虑了900个三位正整数。[法二]main()
{intg,s,b;for(b=1;b<=9;b++)for(s=0;s<=9;s++)
for(g=0;g<=9;g++)if(b*b*b+s*s*s+g*g*g==b*100+s*10+g)
printf("%dn",b*100+s*10+g);}【解析】此方法是用1到9做百
位数字、0到9做十位和个位数字,将组成的三位正整数与每
一组的三个数的立方和进行比较,一旦相等就输出。共考虑了
900个组合(外循环单独执行的次数为9,两个内循环单独执行
的次数分别为10次,故if语句被执行的次数为9×10×10=900),
即900个三位正整数。与法一判断的次数一样。
C语言常用算法2.排序(1)冒泡排序(起泡排序)假设要
对含有n个数的序列进行升序排列,冒泡排序算法步骤是:
①从存放序列的数组中的第一个元素开始到最后一个元素,依
次对相邻两数进行比较,若前者大后者小,则交换两数的位置;
②第①趟结束后,最大数就存放到数组的最后一个元素里了,
然后从第一个元素开始到倒数第二个元素,依次对相邻两数进
行比较,若前者大后者小,则交换两数的位置;③重复步骤
①n-1趟,每趟比前一趟少比较一次,即可完成所求。例1、
任意读入10个整数,将其用冒泡法按升序排列后输出。
#definen10main(){inta[n],i,j,t;for(i=0;i scanf("%d",&a[i]);for(j=1;j<=n-1;j++)/*n个数处理n-1趟*/ for(i=0;i<=n-1-j;i++)/*每趟比前一趟少比较一次*/ if(a[i]>a[i+1]){t=a[i];a[i]=a[i+1];a[i+1]=t;}for(i=0;i printf("%dn",a[i]);}(2)选择法排序选择法排序是相对好理解 的排序算法。假设要对含有n个数的序列进行升序排列,算法 步骤是:①从数组存放的n个数中找出最小数的下标(算法 见下面的“求最值”),然后将最小数与第1个数交换位置;② 除第1个数以外,再从其余n-1个数中找出最小数(即n个数 中的次小数)的下标,将此数与第2个数交换位置;③重复步 骤①n-1趟,即可完成所求。例1、任意读入10个整数,将其 用选择法按升序排列后输出。#definen10main(){int a[n],i,j,k,t;for(i=0;i /*处理n-1趟*/{k=i;/*总是假设此趟处理的第一个(即全 部数的第i个)数最小,k记录其下标*/for(j=i+1;j if(a[j] for(i=0;i 地掌握此算法,先请了解“有序序列的插入算法”,就是将某数 据插入到一个有序序列后,该序列仍然有序。插入算法参见下 面的“数组元素的插入”。 C语言常用算法例1、将任意读入的整数x插入一升序数列后, 数列仍按升序排列。#definen10main(){inta[n]={- 1,3,6,9,13,22,27,32,49},x,j,k;/*注意留一个空间给待插数*/ scanf("%d",&x);if(x>a[n-2])a[n-1]=x;/*比最后一个数还大就 往最后一个元素中存放*/else/*查找待插位置*/{j=0; while(ja[j])j++;/*从最后一个数开始直到待插位 置上的数依次后移一位*/for(k=n-2;k>=j;k--)a[k+1]=a[k]; a[j]=x;/*插入待插数*/}for(j=0;j<=n-1;j++)printf("%d ",a[j]);}插入法排序的要领就是每读入一个数立即插入到最终 存放的数组中,每次插入都使得该数组有序。例2、任意读入 10个整数,将其用插入法按降序排列后输出。#definen10 main(){inta[n],i,j,k,x;scanf("%d",&a[0]);/*读入第一个数,直 接存到a[0]中*/for(j=1;j 序插入到数组a中*/{scanf("%d",&x);if(x 比原数列最后一个数还小就往最后一个元素之后存放新读的数 */else/*以下查找待插位置*/{i=0;while(x 1)i++;/*以下for循环从原最后一个数开始直到待插位置上 的数依次后移一位*/for(k=j-1;k>=i;k--)a[k+1]=a[k];a[i]=x; /*插入待插数*/}}for(i=0;i (4)归并排序即将两个都升序(或降序)排列的数据序列 合并成一个仍按原序排列的序列。例1、有一个含有6个数据 的升序序列和一个含有4个数据的升序序列,将二者合并成一 个含有10个数据的升序序列。#definem6#definen4main() {inta[m]={-3,6,19,26,68,100},b[n]={8,10,12,22};inti,j,k,c[m+n]; C语言常用算法i=j=k=0;while(i 的较小数依次存放到c数组中*/{if(a[i] else{c[k]=b[j];j++;}k++;}while(i>=m&&j 部存放完毕,将b中余下的数全部存放到c中*/{c[k]=b[j];k++; j++;}while(j>=n&&i 余下的数全部存放到c中*/{c[k]=a[i];k++;i++;} for(i=0;i (即线性查找)顺序查找的思路是:将待查找的量与数组中的 每一个元素进行比较,若有一个元素与之相等则找到;若没有 一个元素与之相等则找不到。例1、任意读入10个数存放到数 组a中,然后读入待查找数值,存放到x中,判断a中有无与 x等值的数。#defineN10main(){inta[N],i,x;for(i=0;i scanf("%d",&a[i]);/*以下读入待查找数值*/scanf("%d",&x); for(i=0;i printf("Found!n");elseprintf("Notfound!n");}(2)折半查找 (即二分法)顺序查找的效率较低,当数据很多时,用二分法 查找可以提高效率。使用二分法查找的前提是数列必须有序。 二分法查找的思路是:要查找的关键值同数组的中间一个元素 比较,若相同则查找成功,结束;否则判别关键值落在数组的 哪半部分,就在这半部分中按上述方法继续比较,直到找到或 数组中没有这样的元素值为止。例1、任意读入一个整数x, 在升序数组a中查找是否有与x等值的元素。#definen10 main(){inta[n]={2,4,7,9,12,25,36,50,77,90};int x,high,low,mid;/*x为关键值*/scanf("%d",&x);high=n-1; low=0;mid=(high+low)/2;while(a[mid]!=x&&low {if(x C语言常用算法elselow=mid+1;/*修改区间下界*/ mid=(high+low)/2;}if(x==a[mid]) printf("Found%d,%dn",x,mid);elseprintf("Notfoundn");} 三、数值计算常用经典算法:1.级数计算级数计算的关键是 “描述出通项”,而通项的描述法有两种:一为直接法、二为间 接法又称递推法。直接法的要领是:利用项次直接写出通项式; 递推法的要领是:利用前一个(或多个)通项写出后一个通项。 可以用直接法描述通项的级数计算例子有:(1) 1+2+3+4+5+„„(2)1+1/2+1/3+1/4+1/5+„„等等。可以用间接法 描述通项的级数计算例子有:(1) 1+1/2+2/3+3/5+5/8+8/13+„„(2)1+1/2!+1/3!+1/4!+1/5!+„„等 等。(1)直接法求通项例1、求1+1/2+1/3+1/4+1/5+„„+1/100 的和。main(){floats;inti;s=0.0;for(i=1;i<=100;i++) s=s+1.0/i;printf("1+1/2+1/3+...+1/100=%fn",s);}【解析】 程序中加粗部分就是利用项次i的倒数直接描述出每一项,并 进行累加。注意:因为i是整数,故分子必须写成1.0的形式! (2)间接法求通项(即递推法)例2、计算下列式子前20项 的和:1+1/2+2/3+3/5+5/8+8/13+„„。[分析]此题后项的分子是 前项的分母,后项的分母是前项分子分母之和。main() {floats,fz,fm,t,fz1;inti;s=1;/*先将第一项的值赋给累加器 s*/fz=1;fm=2;t=fz/fm;/*将待加的第二项存入t中*/ for(i=2;i<=20;i++){s=s+t;/*以下求下一项的分子分母*/ fz1=fz;/*将前项分子值保存到fz1中*/fz=fm;/*后项分 子等于前项分母*/fm=fz1+fm;/*后项分母等于前项分子、分 母之和*/ C语言常用算法t=fz/fm;}printf("1+1/2+2/3+...=%fn",s);} 下面举一个通项的一部分用直接法描述,另一部分用递推法描 述的级数计算的例子:n21例3、计算级数的值,当通项的 绝对值小于eps时计算停止。n!20#include floatg(floatx,floateps);main(){floatx,eps; scanf("%f%f",&x,&eps);printf("n%f,%fn",x,g(x,eps));}float g(floatx,floateps){intn=1;floats,t;s=1;t=1;do {t=t*x/(2*n);s=s+(n*n+1)*t;/*加波浪线的部分为直接法描 述部分,t为递推法描述部分*/n++;}while(fabs(t)>eps); returns;}2.一元非线性方程求根(1)牛顿迭代法牛顿迭代 法又称牛顿切线法:先任意设定一个与真实的根接近的值x作 为第一次近似根,由0x求出f(x),过(x,f(x))点做f(x)的切线,交 x轴于x,把它作为第二次近似根,再由x求出f(x),0000111过(x, f(x))点做f(x)的切线,交x轴于x,„„如此继续下去,直到足够 接近(比如|x-x|<1e-61120*时)真正的根x为止。而f '(x)=f(x)/(x-x)所以x=x-f(x)/f'(x)例如,用牛顿 迭代法求下列方程在1.5附近的根:2x-4x+3x-6=0。#include "math.h"main() C语言常用算法{floatx,x0,f,f1;x=1.5;do{x0=x; f=2*x0*x0*x0-4*x0*x0+3*x0-6;f1=6*x0*x0-8*x0+3;x=x0- f/f1;}while(fabs(x-x0)>=1e-5);printf("%fn",x);}(2)二分法 算法要领是:先指定一个区间[x,x],如果函数f(x)在此区间是 单调变化的,则可以根据f(x)121和f(x)是否同号来确定方程 f(x)=0在区间[x,x]内是否有一个实根;如果f(x)和f(x)同号,则 f(x)21212在区间[x,x]内无实根,要重新改变x和x的值。当确定 f(x)在区间[x,x]内有一个实根后,可121212采取二分法将[x,x]一 分为二,再判断在哪一个小区间中有实根。如此不断进行下去, 直到小区间12足够小为止。具体算法如下:(1)输入x和x 的值。12(2)求f(x)和f(x)。12(3)如果f(x)和f(x)同号说明在 [x,x]内无实根,返回步骤(1),重新输入x和x的值;若 f(x)1212121和f(x)不同号,则在区间[x,x]内必有一个实根,执行 步骤(4)。212(4)求x和x的中点:x=(x+x)/2。12012(5) 求f(x)。0(6)判断f(x)与f(x)是否同号。01①如果同号,则应 在[x,x]中寻找根,此时x已不起作用,用x代替x,用f(x)代替 f(x)。0210101②如果不同号,则应在[x,x]中寻找根,此时x已不 起作用,用x代替x,用f(x)代替f(x)。1020202-5-5(7)判断f(x) 的绝对值是否小于某一指定的值(例如10)。若不小于10,则 返回步骤(4)重0复执行步骤(4)、(5)、(6);否则执行步骤 (8)。(8)输出x的值,它就是所求出的近似根。032例如, 用二分法求方程2x-4x+3x-6=0在(-10,10)之间的根。#include "math.h"main(){floatx1,x2,x0,fx1,fx2,fx0;do{printf("Enter x1&x2");scanf("%f%f",&x1,&x2);fx1=2*x1*x1*x1- 4*x1*x1+3*x1-6;fx2=2*x2*x2*x2-4*x2*x2+3*x2- 6;}while(fx1*fx2>0);do{x0=(x1+x2)/2;fx0=2*x0*x0*x0- 4*x0*x0+3*x0-6;if((fx0*fx1)<0){x2=x0;fx2=fx0;}else {x1=x0;fx1=fx0;}}while(fabs(fx0)>1e-5);printf("%fn",x0);} 3.梯形法计算定积分 C语言常用算法bf(x)dx定积分的几何意义是求曲线y=f(x)、 x=a、x=b以及x轴所围成的面积。a可以近似地把面积视为若 干小的梯形面积之和。例如,把区间[a,b]分成n个长度相等的 小区间,每个小区间的长度为h=(b-a)/n,第i个小梯形的面积 为[f(a+(i-1)·h)+f(a+i·h)]·h/2,将n个小梯形面积加起来就得到定 积分的近似值: 根据以上分析,给出“梯形法”求定积分的N-S结构图: 输入区间端点:a,b输入等分数nh=(b-a)/2,s=0i从1到n si=(f(a+(i-1)*h)+f(a+i*h))*h/2s=s+si输出s上述程序的几何意义 比较明显,容易理解。但是其中存在重复计算,每次循环都要 计算小梯形的上、下底。其实,前一个小梯形的下底就是后一 个小梯形的上底,完全不必重复计算。为此做出如下改进: 矩形法求定积分则更简单,就是将等分出来的图形当作矩形, 而不是梯形。4例如:求定积分的值。 等分数n=1000。0 C语言常用算法#include"math.h"floatDJF(floata,floatb) {floatt,h;intn,i;floatHSZ(floatx);n=1000;h=fabs(a-b)/n; t=(HSZ(a)+HSZ(b))/2;for(i=1;i<=n-1;i++)t=t+HSZ(a+i*h);t=t*h; return(t);}floatHSZ(floatx){return(x*x+3*x+2);}main(){float y;y=DJF(0,4);printf("%fn",y);}四、其他常见算法1.迭代法 其基本思想是把一个复杂的计算过程转化为简单过程的多次重 复。每次重复都从旧值的基础上递推出新值,并由新值代替旧 值。例如,猴子吃桃问题。猴子第一天摘下若干个桃子,当即 吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的 桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩 下的一半零一个。到第10天早上想再吃时,就只剩一个桃子了。 编程求第一天共摘多少桃子。main(){intday,peach; peach=1;for(day=9;day>=1;day--)peach=(peach+1)*2; printf("Thefirstday:%dn",peach);}a又如,用迭代法求x=的 根。求平方根的迭代公式是:x=0.5×(x+a/x)n+1nn[算法](1) 设定一个初值x。0(2)用上述公式求出下一个值x。1(3)再 将x代入上述公式,求出下一个值x。12(4)如此继续下去, 直到前后两次求出的x值(x和x)满足以下关系:n+1n-5|x- x|<10n+1n#include"math.h"main(){floata,x0,x1; C语言常用算法scanf("%f",&a);x0=a/2;x1=(x0+a/x0)/2; do{x0=x1;x1=(x0+a/x0)/2;}while(fabs(x0-x1)>=1e-5); printf("%fn",x1);}2.进制转换(1)十进制数转换为其他进制 数一个十进制正整数m转换成r进制数的思路是,将m不断 除以r取余数,直到商为0时止,以反序输出余数序列即得到 结果。注意,转换得到的不是数值,而是数字字符串或数字串。 例如,任意读入一个十进制正整数,将其转换成二至十六任意 进制的字符串。voidtran(intm,intr,charstr[],int*n){char sb[]="ABCDEF";inti=0,g;do{g=m%r;str[i]=sb[g]; m=m/r;i++;}while(m!=0);*n=i;}main(){intx,r0; /*r0为进制基数*/inti,n;/*n中存放生成序列的元素个数*/ chara[50];scanf("%d%d",&x,&r0);if(x>0&&r0>=2&&r0<=16) {tran(x,r0,a,&n);for(i=n-1;i>=0;i--)printf("%c",a[i]); printf("n");}elseexit(0);}(2)其他进制数转换为十进制 数其他进制整数转换为十进制整数的要领是:“按权展开”,例 如,有二进制数101011,则其十543210……a进制形式为 1×2+0×2+1×2+0×2+1×2+1×2=43。若r进制数aa(n位数)转换 成n21n-110十进制数,方法是a×r+……a×r+a×r。n21注意:其他进 制数只能以字符串形式输入。例1、任意读入一个二至十六进 制数(字符串),转换成十进制数后输出。#include"string.h" #include"ctype.h" C语言常用算法main(){charx[20];intr,d;gets(x);/*输入 一个r进制整数序列*/scanf("%d",&r);/*输入待处理的进制基 数2-16*/d=Tran(x,r);printf("%s=%dn",x,d);}intTran(char *p,intr){intd,i,cr;charfh,c;d=0;fh=*p;if(fh=='-')p++; for(i=0;i='A') cr=toupper(c)-'A'+10;elsecr=c-'0';d=d*r+cr;}if(fh=='-') d=-d;return(d);}3.矩阵转置矩阵转置的算法要领是:将一 个m行n列矩阵(即m×n矩阵)的每一行转置成另一个n×m 矩阵的相应列。例1、将以下2×3矩阵转置后输出。即将1 23转置成1445625 36main(){inta[2][3],b[3][2],i,j,k=1;for(i=0;i<2;i++) for(j=0;j<3;j++)a[i][j]=k++;/*以下将a的每一行转存到b 的每一列*/for(i=0;i<2;i++)for(j=0;j<3;j++)b[j][i]=a[i][j]; for(i=0;i<3;i++)/*输出矩阵b*/{for(j=0;j<2;j++) printf("%3d",b[i][j]);printf("n");}} C语言常用算法4.字符处理(1)字符统计:对字符串中 各种字符出现的次数的统计。典型例题:任意读入一个只含小 写字母的字符串,统计其中每个字母的个数。#include "stdio.h"main(){chara[100];intn[26]={0};inti;/*定义26个计 数器并置初值0*/gets(a);for(i=0;a[i]!='0';i++)/*n[0]中存 放’a’的个数,n[1]中存放’b’的个数……*/n[a[i]-'a']++;/*各字 符的ASCII码值减去’a’的ASCII码值,正好得到对应计数器下标 */for(i=0;i<26;i++)if(n[i]!=0)printf("%c:%dn",i+'a',n[i]);} (2)字符加密例如、对任意一个只含有英文字母的字符串, 将每一个字母用其后的第三个字母替代后输出(字母X后的第 三个字母为A,字母Y后的第三个字母为B,字母Z后的第三 个字母为C。)#include"stdio.h"#include"string.h"main() {chara[80]="China";inti;for(i=0;i if(a[i]>='x'&&a[i]='X'&&a[i]<='Z')a[i]=a[i]-26+3; elsea[i]=a[i]+3;puts(a);}5.整数各数位上数字的获取算法核 心是利用“任何正整数整除10的余数即得该数个位上的数字”的 特点,用循环从低位到高位依次取出整数的每一数位上的数字。 例1、任意读入一个5位整数,输出其符号位及从高位到低位 上的数字。main(){longx;intw,q,b,s,g;scanf("%ld",&x); if(x<0){printf("-,");x=-x;}w=x/10000;/*求万位上的数字*/ q=x/1000%10;/*求千位上的数字*/b=x/100%10;/*求百位 上的数字*/s=x/10%10;/*求十位上的数字*/g=x%10; /*求个位上的数字*/printf("%d,%d,%d,%d,%dn",w,q,b,s,g);} 例2、任意读入一个整数,依次输出其符号位及从低位到高位 上的数字。[分析]此题读入的整数不知道是几位数,但可以用 以下示例的方法完成此题: C语言常用算法例如读入的整数为3796,存放在x中,执行 x%10后得余数为6并输出;将x/10得379后赋值给x。再执 行x%10后得余数为9并输出;将x/10得37后赋值给x„„直到 商x为0时终止。main(){longx;scanf("%ld",&x);if(x<0) {printf("-");x=-x;}do/*为了能正确处理0,要用 do_while循环*/{printf("%d",x%10); x=x/10;}while(x!=0);printf("n");}例3、任意读入一个整 数,依次输出其符号位及从高位到低位上的数字。[分析]此题 必须借助数组将依次求得的低位到高位的数字保存后,再逆序 输出。main(){longx;inta[20],i,j;scanf("%ld",&x);if(x<0) {printf("-");x=-x;}i=0;do{a[i]=x%10;x=x/10; i++;}while(x!=0);for(j=i-1;j>=0;j--)printf("%d",a[j]); printf("n");}6.辗转相除法求两个正整数的最大公约数该算 法的要领是:假设两个正整数为a和b,先求出前者除以后者 的余数,存放到变量r中,若r不为0,则将b的值得赋给a, 将r的值得赋给b;再求出a除以b的余数,仍然存放到变量r 中„„如此反复,直至r为0时终止,此时b中存放的即为原来 两数的最大公约数。例1、任意读入两个正整数,求出它们的 最大公约数。[法一:用while循环时,最大公约数存放于b中] main(){inta,b,r;doscanf("%d%d",&a,&b); while(a<=0||b<=0);/*确保a和b为正整数*/r=a%b; while(r!=0){a=b;b=r;r=a%b;}printf("%dn",b);}[法二:用 do…while循环时,最大公约数存放于a中] C语言常用算法main(){inta,b,r;doscanf("%d%d",&a,&b); while(a<=0||b<=0);/*确保a和b为正整数*/do {r=a%b;a=b;b=r;}while(r!=0);printf("%dn",a);}【引申】 可以利用最大公约数求最小公倍数。提示:两个正整数a和b 的最小公倍数=a×b/最大公约数。例2、任意读入两个正整数, 求出它们的最小公倍数。[法一:利用最大公约数求最小公倍数] main(){inta,b,r,x,y;doscanf("%d%d",&a,&b); while(a<=0||b<=0);/*确保a和b为正整数*/x=a;y=b; /*保留a、b原来的值*/r=a%b;while(r!=0){a=b;b=r;r=a%b;} printf("%dn",x*y/b);}[法二:若其中一数的最小倍数也是另 一数的倍数,该最小倍数即为所求]main(){inta,b,r,i;do scanf("%d%d",&a,&b);while(a<=0||b<=0);/*确保a和b为正 整数*/i=1;while(a*i%b!=0)i++;printf("%dn",i*a);} 7.求最值即求若干数据中的最大值(或最小值)。算法要领 是:首先将若干数据存放于数组中,通常假设第一个元素即为 最大值(或最小值),赋值给最终存放最大值(或最小值)的 max(或min)变量中,然后将该量max(或min)的值与数组 其余每一个元素进行比较,一旦比该量还大(或小),则将此元 素的值赋给max(或min)„„所有数如此比较完毕,即可求得 最大值(或最小值)。例1、任意读入10个数,输出其中的最 大值与最小值。#defineN10main(){inta[N],i,max,min; for(i=0;i for(i=1;i C语言常用算法if(a[i]>max)max=a[i];elseif(a[i] min=a[i];printf("max=%d,min=%dn",max,min);}8.判断素 数素数又称质数,即“只能被1和自身整除的大于1的自然数”。 判断素数的算法要领就是依据数学定义,即若该大于1的正整 数不能被2至自身减1整除,就是素数。例1、任意读入一个 正整数,判断其是否为素数。main(){intx,k;do scanf("%d",&x);while(x<=1);/*确保读入大于1的正整数*/ for(k=2;k<=x-1;k++)if(x%k==0)break;/*一旦能被2~自身-1整 除,就不可能是素数*/if(k==x)printf("%dissushun",x); elseprintf("%disnotsushun",x);}以上例题可以用以下两种变 形来解决(需要使用辅助判断的逻辑变量):【变形一】将“2~ 自身-1”的范围缩小至“2~自身的一半”main(){intx,k,flag; doscanf("%d",&x);while(x<=1);flag=1;/*先假设x就是素数 */for(k=2;k<=x/2;k++)if(x%k==0){flag=0;break;}/*一旦不可 能是素数,即置flag为0*/if(flag==1)printf("%dis sushun",x);elseprintf("%disnotsushun",x);}【变形二】将 “2~自身-1”的范围缩小至“2~自身的平方根”#include"math.h" main(){intx,k,flag;doscanf("%d",&x);while(x<=1);flag=1; /*先假设x就是素数*/for(k=2;k<=(int)sqrt(x);k++) if(x%k==0){flag=0;break;}/*一旦不可能是素数,即置flag为0*/ if(flag==1)printf("%dissushun",x);elseprintf("%disnot sushun",x);}例2、用筛选法求得100以内的所有素数。算法 为:(1)定义一维数组a,其初值为:2,3,„„,100; (2)若a[k]不为0,则将该元素以后的所有a[k]的倍数的数组 元素置为0;(3)a中不为0的元素,均为素数。 #include C语言常用算法#includemain(){int k,j,a[101];clrscr();/*清屏函数*/for(k=2;k<101;k++)a[k]=k; for(k=2;k if(a[k]!=0&&a[j]!=0)if(a[j]%a[k]==0)a[j]=0; for(k=2;k<101;k++)if(a[k]!=0)printf("%5d",a[k]);}9.数组元素 的插入、删除(1)数组元素的插入此算法一般是在已经有序 的数组中再插入一个数据,使数组中的数列依然有序。算法要 领是:假设待插数据为x,数组a中数据为升序序列。①先将 x与a数组当前最后一个元素进行比较,若比最后一个元素还 大,就将x放入其后一个元素中;否则进行以下步骤;②先查 找到待插位置。从数组a的第1个元素开始找到不比x小的第 一个元素,设其下标为i;③将数组a中原最后一个元素至第 i个元素依次一一后移一位,让出待插数据的位置,即下标为i 的位置;④将x存放到a(i)中。例题参见前面“‘排序’中插入法 排序的例1”。(2)数组元素的删除此算法的要领是:首先要 找到(也可能找不到)待删除元素在数组中的位置(即下标), 然后将待删元素后的每一个元素向前移动一位,最后将数组元 素的个数减1。例1、数组a中有若干不同考试分数,任意读 入一个分数,若与数组a中某一元素值相等,就将该元素删除。 #defineN6main(){intfs[N]={69,90,85,56,44,80},x;inti,j,n; n=N;scanf("%d",&x);/*任意读入一个分数值*//*以下查找 待删分数的位置,即元素下标*/for(i=0;i if(fs[i]==x)break;if(i==n)printf("Notfound!n");else/*将 待删位置之后的所有元素一一前移*/{for(j=i+1;j 1]=fs[j];n=n-1;/*元素个数减1*/ C语言常用算法}for(i=0;i 10.二维数组的其他典型问题(1)方阵的特点行列相等的矩 阵又称方阵。其两条对角线中“”方向的为主对角线,“/”方向 的为副对角线。主对角线上各元素的下标特点为:行列值相等; 副对角线上各元素的下标特点为:行列值之和都为阶数加1。 主对角线及其以下部分(行值大于列值)称为下三角。例1、 输出如下5阶方阵。31 223331233331#defineN5main(){int a[N][N],i,j;for(i=0;i a[i][j]=1;elseif(i for(i=0;i printf("n");}}例2、输出如下5阶方阵。12345 23456345674567856789 #defineN5main(){inta[N][N],i,j;for(i=0;i for(j=0;j 每个元素,其值等于行列值之和+1*/ C语言常用算法for(i=0;i printf("%3d",a[i][j]);printf("n");}}(2)杨辉三角形n0杨辉 三角形的每一行是(x+y)的展开式各项的系数。例如第一行是 (x+y),其系数为1;第二1222行是(x+y),其系数为1,1;第三 行是(x+y),其展开式为x+2xy+y,系数分别为1,2,1;„„直观 形式如下:464115 101051„„分析以上形式,可以发现其规律:是n阶方阵 的下三角,第一列和主对角线均为1,其余各元素是它的上一 行、同一列元素与上一行、前一列元素之和。例1、编程输出 杨辉三角形的前10行。#defineN10main(){inta[N][N],i,j; for(i=0;i 1;j++)a[i][j]=a[i-1][j-1]+a[i-1][j];for(i=0;i {for(j=0;j<=i;j++)printf("%4d",a[i][j]);printf("n");}} 例2、以等腰三角形的形状输出杨辉三角形的前5行。 1111211331 14641#defineN5main(){inta[N][N],i,j; for(i=0;i C语言常用算法a[i][0]=a[i][i]=1;for(i=0;i for(j=1;j {for(j=N-i;j>=0;j--)printf("");/*输出时每行前导空格递减*/ for(j=0;j<=i;j++)printf("%4d",a[i][j]);printf("n");}}