1、投影8 省二级C算法考点JJH 算法考点非数值计算常用经典算法基本操作:交换 (*)实现变量的值的交换最常用的方法是借助一个临时变量来实现将两个数的值进行交换。void swap(int x, int y) int temp; temp=x; x=y; y=temp;值传递,单向的,如果主函数调用了此函数,尽管形式参数x和y的值交换了,而主函数中的实际参数是不会改变的。要想实现地址传递,应该用指针实现。void swap(int *x, int *y) int temp; temp=*x; *x=*y; *y=temp;函数调用时将实参的地址传递给指针x和y,例如:swap(&a, &b);实
2、现x和y指向的地址单元的值的交换,即a和b的值的交换。1排序 (*)排序就是将数组中的元素按从大到小的顺序或者从小到大的顺序重新排列。1)冒泡排序 (*)下面的函数是按升序从前往后排。 void BubbleSort(int a,int n) int i,j, tmp;大数移到了最后 for(i=0;in-1;i+) /*排序趟次*/ for(j=0; jaj+1) /*从小到大*/ tmp=aj; aj=aj+1; aj+1=tmp; /*交换aj与aj+1,大数后移*/2)选择排序 (*)算法思想:从待排序的序列中,选择最小的一个记录,与第一个数据交换;然后从不包括第一个记录的序列中选择最
3、小一个与第二个交换;如此重复,直至只剩一个数据为止。void SelectSort(int a,int n) int i,j,min_i,tmp; for(i=0; in-1; i+) min=i; /*假设第一个数最小,记录其下标*/ for(j=i+1; jn; j+) if(ajamin) min=j; /*找最小的,将最小数的下标记录下来*/ if(i!=min) tmp=ai; ai=amin; amin=tmp; /*将最小的数与第一个数进行交换*/ 3)插入排序 (*)算法思想:插入排序的基本操作就是将一个数据插入到已经排好序的有序数组中,从而得到一个新的、个数加1的有序数组。v
4、oid InsertSort(int a,int n) int i,j,tmp; for(i=1; i=0 & ajtmp; j-) aj+1=tmp?; aj+1=aj; /* 大于tmp的数向后移位 */ /* tmp归位 */ 2归并(或合并) (*)归并就是将两个有序数组A、B合并成另一个有序的数组C(升序或降序)。算法步骤:1 先在A、B数组中各取第一个元素进行比较,将小的元素放入C中。2 取小的元素所在数组的下一个元素与另一个数组中上次比较后较大的元素比较。3 重复上述比较过程,直到某个数组被先排完。4 将另一个数组剩余元素抄入C中,合并排序完成。void merge(int am
5、,int bn,int c) ia=0;ib=0;ic=0;while(iam & ibn) if (aiabib) cic=aia;ia+; else cic=bib;ib+; ic+; while(iam) cic=aia;ia+;ic+; /*a中剩余元素抄入c中*/while(ibn) cic=bib;ib+;ic+; 3查找 (*)查找,就是判断一个数是否是数组中的某个元素。最常见最简单的查找方法为线性法查找,对于已经排过序的数组,可以采用折半法查找。1)线性法查找没有排序的数组,只能采用线性法查找基本思想:将x与数组中的各个元素从头到尾进行比较,找到返回数组下标,找不到,返回-1。
6、#define N 10int find(int aN,int key) for(i=0; iN; i+) if(ai=key) return (i); break; /*返回数组元素下标*/ if(i=N) return (-1); 2)折半法查找折半查找法也称为二分查找法,只能对有序数组进行查找。将n个元素分成个数大致相同的两半,取an/2与欲查找的x作比较,如果x=an/2则找到x,算法终止。如果xan/2,则我们只要在数组a的右半部分继续搜索x。#define N 10int find(int aN,int key) int m;p=0;q=N-1; /*p为第1个元素的下标,q为最后
7、一个元素的下标*/while(p=q) m=(p+q)/2; /*m为中间元素的下标*/ if (am=key) return (m); break; else if(keyq) return (-1);4穷举 (*)穷举法的基本思想是:一一列举各种可能的情况,并判断哪一种可能是符合要求的解。这是一种在“没有其它办法的情况的方法”,是一种最“笨”的方法,然而对一些无法用解析法求解的问题往往能奏效,通常采用循环来处理穷举问题。【例题】有1、2、3、4四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去掉不满足
8、条件的排列。main() int i,j,k;for(i=1;i5;i+)*以下为三重循环*/for(j=1;j5;j+) for (k=1;k5;k+) if (i!=k&i!=j&j!=k) /*确保i、j、k三位互不相同*/ printf(%d,%d,%dn,i,j,k); 数值计算常用经典算法 级数计算(递推法) (*)累加 (*)使用循环时,要注意根据问题确定循环变量的初值、终值或结束条件,更要注意用来表示最后结果的初值。用c语言实现1+2+3+4+5+n的累加。【方法1】for循环实现 int add(int n) int i,sum=0; for(i=1;i=n;i+) sum=
9、sum+i; return sum; 【方法2】while循环实现 int add(int n) int i,sum; sum=0; i=1; while(i=0) int product (int n) int i,p=1; for(i=2;i=n;i+) p=p*i; return p; 如果n的值比较大,考虑累乘的结果可能会超过32767,函数返回值应定义为长整型,确保程序运行的正确。 long func(int n) int i; long p=1; for(i=2;i=n;i+) p*=i; return p; 用递推法求n!的程序段如下: for (fac=1,i = 2; i=n
10、; i+) fac=fac*i ; 【例题】有一分数序列:求出这个数列的前20项之和。本题主要要抓住分子与分母的变化规律。 main() int n,t,number=20;float a=2,b=1,s=0; /*a表示分子,b表示分母*/for(n=1;n=number;n+) s=s+a/b; t=a; a=a+b; b=t; printf(sum is %9.6fn,s);【例题】求1+2!+3!+.+20!的和main() float n,s=0,t=1; for(n=1;n=20;n+)t*=n; s+=t; printf(1+2!+3!.+20!=%en,s);运行结果为:1+2
11、!+3!.+20!=2.561327e+18本题将变量定义为float,因为long型数据的范围为-21亿21亿。无法容纳求得的结果。int型的就更不用说了,表示范围只有-3276832767。【例题】以下程序的功能是:根据公式和精度计算的近似值。#include #include double PI(double eps) double s=0,t=1.0;int n; for(n=1;_ ;n+) s+=t; t=t*(n-1)/(2*n-1)?_ ; return 2.0*s;void main() double e=1e-6; /* e是计算精度要求,这里表示允许运算结果值在小数点后第
12、6位有误差 */printf(%f,_);【例题】以下程序通过给出的公式计算的近似值,计算过程在所加项的值小于10-6时终止。 #include main() double sum=0.5,t,t1,t2,t3; int odd=1,even=2; t=t1=t2=1.0;t3=0.5; while(t1e-10) t1=_t1*odd/even?_ ; odd+=2;even+=2; t2=1.0/odd; t3=_t3*0.5*0.5?_; t=t1*t2*t3; sum+=t; printf(nPI=%.8lf,_sum_;解决各类问题的一般算法数组问题1求最大、最小值 (*)1)查找一
13、维数组a 中的最大值,n为数组的大小 int funmax (int a , int n) int i,max=a0; for( i=1;iai) max=ai; return max; 2)查找二维数组a中的最小值有一个34的矩阵,求所有元素的最小值。二维数组作函数的参数,第一维的长度可以缺省,第二维的长度不能缺省。 int funmin(int a 4) int i,j,min;min=a00;for(i=0;i3;i+) for(j=0;j4;j+) if(aijmin) min=aij;return min;2求和及平均值 (*) 求数组的平均值,先用循环将数组的所有元素相加,最后返回
14、所得的和除以数组元素的个数。 int average(int a , int n) int i,avg=0;for(i=0;in;i+) avg=avg+ai; /*若avg的初值为a0,则i从1开始*/return avg/n;若求数组的和,则return语句改为return avg。若所求的数组的平均值不是从第一个元素开始的,不管从那个元素开始,只要将开始元素的地址作为实际参数即可。例如,数组a共有20个元素,求最后5个元素的平均值的调用方式为:average(&a15 , 5);3计数 (*)求满足要求的数的个数。一般在循环中对每一个元素都用if语句进行判断,满足条件的话,计数的变量增1
15、。例如:对数组中的n 个学生成绩,求不及格人数的个数。 int count(int a,int n) int c=0; for(i=0;in;i+) if(ai60) c+; return c; 4数组元素逆置 (*)算法思想:将数组元素的第一个与最后一个元素交换位置,第二个元素与倒数第二个元素交换位置。需要注意的是,只能遍历数组的一半元素,如果遍历整个数组,每个元素都做了两次交换,最终又回到原来的位置上。exchange(int a, int n) int i, t; for(i=0;ii; j-) aj+1=aj; /*移位*/ai+1=x; /* 插入x */2)在已排序的数组中插入一个
16、数有一个已经排好序的数组,现有一个数x,要求按原来的规律将它插入数组中。首先判断此数是否大于最后一个数,然后再考虑插入中间的情况,找插入点,先将插入点之后的数,依次后移一个位置。#define N 6void insert(int aN,int num) int i,j; if (numaN-2) aN-1=num; /*插在最后*/ else for(i=0; inum) /*找插入点,插在ai位置*/ for(j=N-2; j=i;j-) aj+1=aj; /*将ai以后的元素从最后一个元素开始后移*/ ai=num; /*将num放在ai处*/ break; 6删除数组中的一个元素ai
17、删除数组中的元素ai,就是将ai以后的元素往前移一个位置。void del (int a,int n,int i ) int j ;for(j=i; jn-1; j+) aj=aj+1;整数问题1素数问题素数是指除1和本身外不能被其他任何整数整除的正整数。1)判断m是否是素数的函数#include int prime(int m) int i,k; k=sqrt(m); /* k是不大于m的平方根的最大整数*/ for (i=2;i=k;i+) if(m%i=0) return 0; /*不是素数,返回0*/ return 1;2)把mn范围内的素数依次放入数组a中,返回素数个数。#inclu
18、de int prime(int aN,int m,int n) int i,k,j; j=0; /*j为素数的个数*/for(i=m;i=n;i+) for(k=2;ksqrt(i) aj+=i; /*i为素数,存入数组*/ return j;2求最大公约数和最小公倍数 1)求最大公约数(欧几里得算法)最大公约数的算法也叫欧几里得算法,采用的是辗转相除法求两数m、n最大公约数,其算法步骤如下:1 对于已知两数m和n,;2 将m除以n得余数r;3 若r为0,则n为求得的最大公约数,算法结束,否则执行下一步;4 n赋给m,r赋给n,再重复执行上面的两步。算法结束时,m中所存放的值即为最大公约数。
19、 gcd( int m, int n) int t,r; if(mn) t=m; m=n; n=t; /*若m=0) num=num*10+n;scanf( %d ,&n); printf(%ld,num);4求反序数和回文数 1)求反序数 将一个数的数字排列顺序完全颠倒过来,就变成另一个数,这个数就是该数的反序数,如123的反序数为321。int inte(int n) int num=0;while(n)num=num*10+n%10;n=n/10; return(num);2)求回文数 一个数与它的反序数相等,这样的数称为回文数。例如12321,6336等就是回文数。判断一个数是否是回文
20、数,先求出它的反序数,再判断两者是否相等。判断n是否是回文数的函数int palin(int n)int s=0; m=n;反序数while(m)s=s*10+m%10;m=m/10;if(s=n) return (1);else return (0);求指定范围内的回文数写一个函数,求指定范围内(m1m2之间)的回文数,保存到指定的数组中,并返回回文数的个数。int palin(long m1,long m2,long x) long i,n,s; /*s是i的回文数*/ int k=0; /*k回文数个数,数组下标*/ for(i=m1;i=m2;i+) n=i;s=0; while(n)
21、 /*求反序数*/ s=s*10+n%10; n=n/10; if(i=s) xk=i;k+; /*若是回文数,放入数组a中*/ return k; /*返回回文数的个数*/5因子、完全数、互满数对 1)求a的因子并存放在数组中因子是指能被a整除的数,包含1和该数本身,真因子包含1不包含本身。int fun(int a, int xN) int i,j=0; for(i=1;i=a;i+) if (a%i=0) xj+=i; return j; /*返回因子的个数*/2)找指定范围内的完全数完全数是指一个正整数的所有真因子之和等于本身的数,因子包含1但不包含本身,例如::6=1+2+3,28=
22、1+2+4+7+14,所以6和28是完全数。int fun(int aN,int m,int n) int i,j,s; int k=0;for(i=m;i=n;i+) s=0; for(j=1;ji;j+) if (i%j=0) s=s+j; if(i=s) ak+=i; return k; 3)互满数对(亲密数对)互满数对是指两个数中,其中的一个数的真因子之和都等于另一个数。即a的真因子之和为b,b的真因子之和为a。如:220与184,1184与1210就是互满数对。int fun(int s2,int m1,int m2) int s1,s2,count,a,i,j;count=0;fo
23、r(a=m1;a=m2;a+) s1=1;s2=1; for (i=2;ia;i+) if (a%i=0) s1=s1+i; for (j=2;js1;j+) if (s1%j=0) s2=s2+j; if (s2=a) & (as1) scount0=a; scount1=s1; count+; return count;6求满足条件的数或数对 本类型的题目是近年考得比较多的类型,其变化也比较多,需要分析,灵活运用。比较简单的如同构数,还有典型的Armstrong数。实际上,素数、回文数、完全数等都是属于满足要求的数。很多问题都是由基本的算法变化来的。1)同构数同构数是其值等于其右边数字平方数的整数。如25, 36都是同构数(25=52, 36=62)。下面的程序是求199之间的所有同构数。main() int i,k; for(i=1; i100; i+) k=i%10; /*求未位数*/if(k*k=i) printf(“%d, “,i); /*输出满足要求的数*/2)Armstrong数一个位的正整数,其各位数的次方之和等于这个数,称这个数为Armstrong数。例如,153135333。163414643444。下面的程序求所有三位和四位数的Armstrong
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1