1、C语言算法C语言算法总结 据我一年来学习C语言,发现其不过如此。语言是什么?是人类思维的表达方式,那C语言是什么,是人类为了让电脑听懂自己的想法,而创造的一个工具。既然,人与人之间这么难的语言大家都掌握了,那C语言又算什么呢。毛泽东告诫我们说:“对于敌人,要在战术上重视它,在战略上藐视它。” 好废话少说,开始讲课。1求素数【思想汇总】求素数是最简单的一个算法,也是最常用的算法,纯数学理论,最简单的方式是先求此数的平方根,再设置一个变量从2到平方根数,判断是否所有的数能否被原数整除。【算法语句】k=sqrt(x)for(i=2;i=1e-5); */x1即为所求。【思想推广】牛顿迭代法求平方根是
2、一种逼近的数学思想,用途十分广泛,如上机指导实验六第三题,arcsh(x)函数。3.求最大公约数,最小公倍数【思想汇总】求此数有三种思想,一是定义法求解,二是相减求等法,三是辗转相除法。具体算法如下。【算法语句】gys(int m,int n) int i,x; x=m=1;i-) if(m%i=0&n%i=0)break;/*此为定义法,先找一个相对最小的数x, return i; 再定义一个变量从x到1递减,判断是否能同时被两个数整除*/gys(int m,int n) while(m!=n) if(mn)m=m-n;/*此为相减求等法,大减小,这样逐步相减,当它相等时, else n=n
3、-m; 即为答案*/ return m;gys(int m,int n) int r; while(r=m%n)!=0) m=n;n=r;/*辗转相除法是最简单的方法,但要好好理解*/ return n;【思想推广】求公约数和公倍数在最近的考试中不常出现,只需理解其原理即可。其思想即是熟练掌握公式。4.数的分解【思想汇总】其思想较为简单,即除以其权重,把数一个个剥离出来,但其实现方式多样,如硬性分解,循环分解,递归分解等。【算法语句】1.硬性分解,所为硬性分解即是已知此数的位数进行的分解,如已知一个5位数的数x,将其分解为ge,shi,bai,qian,wanwan=x/10000;qian=
4、x%10000/1000;bai=x%1000/100;shi=x%100/10;ge=x%10;2.循环分解,循环分解其优点是无需知道数的位数。while(n0) ai=n%10; /*注意:在用此方法是要将数组位数的足够大,并且i要至 n=n/10; 零*/ i+;3.递归法 利用函数的递归也可快速的进行数的分解,其优点是为数不限,比循环分解还要优越,且代码短小精悍,执行时间短。printz(long n) if(n0) printz(n/10);/*先返回除最高位的数,所以最后输出是是按照正向输出的 printf(“%ld”,n%10); */printd(long n) if(n0)
5、printf(“%ld”,n%10);/*先输出个位,再返回除高位,因此这是逆向输出*/ printd(n/10);【思想推广】数的分解形式多样,看个人喜好,可以采取多种方式,最经典的程序莫过于水仙花数,个人比较推荐用递归,代码简单,效率高。5数的合并(乘权求和)【思想汇总】数的合并绝大多数都是一种乘权求和的思想,其思想精髓在于每一位xi乘以其权重Ni在对其求和,公式如下xi* Ni【算法语句】1.将一个八进制的字符串转化为一个十进制的数main() char *p,s6;int n=0; gets(s); for(p=s;*p!=0;p+) n=n*8+*p-0; /*此处即为其算法的核心,
6、每一位上的数乘以权重,再 printf(“%d”,n); 相加*/2.十进制转十六进制c10_16(char *p,int b) int j; while(b0) j=b%16;if(i10) *p=j+48; /*此处是说将每位上的数加上48转换成数字字符*/else *p=j+55; /*若数大于10则转化为字母字符*/b=b/16;p+;*p=0;【思想推广】乘权求和一般用于进制的转换,字符串与整形的转换,补充一个知识点,若遇到字符和数字的转化可用这样几个头文件里包括的函数int atoi(string)(将字符串转化为整形)double atof(string)(将字符串转化为浮点型)
7、string itoa(int)(将整形转化为字符串),在用这些函数时要写#include 6.数组排序【思想汇总】数组排序是最重要的一个程序,主要有两种方法,冒泡法和选择法,相对而讲,选择法更加优越。当然还有更好的快速排序法,这里就不介绍了。【算法语句】1.选择法void sort(inta,int n) int i,j,p,t; for(i=0;in-1;i+) p=i; /*假设第一个是最小的赋值给p*/ for(j=i+1;jn;j+) if(ajap) p=j; /*如果后一位小于占时最小的重新赋值,从小到 if(p!=i)t=ai;ai=ap;ap=t; 大排列*/2.冒泡法voi
8、d sort(int a,int n) int i,j,k; for(i=0;in-1;i+) for(j=0;jaj+1) /*若前一位大于后一位则交换,从小到大排*/ t=aj;aj=aj+1;aj+1=t;【思想推广】选择法是一种假设验证修正的一种数学思想,可用在很多程序上,一定要理解掌握这种思想。冒泡法是逐一递进的方法,先找出最小(大)的置前,再找次小(大)放在第二位以此类推。这两种思想不仅要在数组中运用到,还会在更难得结构公用体,甚至是链表的排列上用到。7.一维数组基本操作(逆置,合并,查找,插入&删除)【思想汇总】一维数组操作十分简单,灵活多变,可以用一般的数组形式表示,也可以用指
9、针,在这里不妨让我总结一下数组与指针表达形式int a100,*p; p=a;第i个元素值*(a+i)*(p+i)aipi第i个元素地址a+ip+i&ai&pi这个表格要牢牢掌握,不能犯错!【算法语句】1.倒置 这里只介绍指针法。void reverse(int *d,int n) int *p1,*p2,t; p1=d;p2=d+n-1; while(p1p2) t=*p1;*p1=*p2;*p2=t;p1+;p2-;2.合并 合并有单纯的两数组合并,也有按照某个规则合并,不管怎样都很简单,这里就不一一写了。3.查找 查找有顺序查找也有折半查找顺序查找是指关键字与数组中每一个进行比较验证,此
10、方法比较浪费时间,但代码简单易掌握int i;for(i=0;in;i+) if(ai=m)return ireturn (-1)还有一种折半查找,此方法速度较快,但须事先将数组排序,代码繁琐,就不介绍了。4插入&删除对于这类操作首先要进行定位,一般用指针来移动定位,在进行插入或删除操做【思想推广】一维数组操作时十分简单的,在二级考试中一般只做为填空或选择,在大题目中一般不出现。一维数组的熟练掌握对后面的二维数组有很大的帮助8.二维数组的操作【思想汇总】二维数组操作是一个很重要的内容,其变化方式也是多种多样,但万变不离其宗,只要你能熟练使用(二维)指针就能轻松应对各种难题。先列出一个重要的表格
11、给大家aij的地址&aijai+j*(a+i)+jaij的值aij*(ai+j)*(*(a+i)+j)(*(a+i)j若int *p=a0 p+i*m+j既是aij的地址(m既是二维数组的列数)上面这张表十分重要,几乎历年的改错题都和二维数组有关,并且都会有一两个错误出自此处【算法语句】1.二维数组转置(上下三角操作)void turn(int a44) int i,j,k; for(i=0;i4;i+) for(j=0;j4;j+) if(ij)t=aij;aij=aji;aji=t;上下三角元素交换void turn(int a44) int i,j,t; for(i=0;i4;i+) f
12、or(j=0;ji;j+) /*此行还可改为for(j=i+1;j4;j+)*/ t=aij;aij=aji;aji=t;2.列(行)互换若要求第A行与第B行互换则void exchange(int a44) int i,k; for(i=0;i4;i+) k=aAi;aAi=aBi;aBi=k /*行互换时,列从0到N变换,再用三 段交换法*/同理可得列互换3.二维函数求和(对角线求和,周边元素求和)对角线求和fsum(int aNN,int n) int i,sum=0; for(i=0;in;i+) sum+=aii+aiN-i-1; return sum;周边元素求和,有两种思维,一是
13、求全体和减去其内部元素之和,二是扫描全体元素,若元素在周边,则累加。我就写一个第二种思维的程序int i,j,sum=0;for(i=0;iN;i+)for(j=0;jN;j+)if(i=0|j=0|i=N-1|j=N-1) /*这是一个判断是否在周边的语句,在写此类语句是sum+=aij; 一定要注意“与”和“或”要弄清楚*/【思想推广】二维数组的操作还远不止这些,但都与此类似,在做这类题目时一定要注意定位准确,操作符合规则,若出现比较繁琐的操作,可考虑化简,或是逆向思考,可以迎刃而解。前面的八个类型是最基本最重要的,一定要超熟练的掌握,后面补充一些比较难的算法,供大家发挥。9.定积分的计算
14、【思想汇总】定积分计算的意义既是函数在某个区间内的面积,可用梯形法进行计算,所谓梯形法,既是将函数在区间内围成的面积分割成无数个小梯形,求出每个梯形的面积,最后求和。梯形法公式为 n-1s=h*f(a)+f(b)/2+f(a+i*h) h=|(b-a)/n|i=1【算法语句】double integral(double (*fun)(),double a,double b,int n) double s,h,y;int i; s=(*fun)(a)+(*fun)(b)/2; /*这里的(*fun)是函数指针,根据自己不同的需 h=(b-a)/n; 要指向不同的原函数*/ for(i=1;iag
15、e 和student1.age 等价。注意p-n+和+p-n的不同。上面讲的是结构体变量的调用,若用指针还可以指向结构体数组struct student stu4; struct student p;p=stu;此时就定义了一指针来指向这个结构体数组要想调用每个元素,需要使用以下循环for(;py) z=x; else z=y; return(z); 2.返回指针的函数(指针函数)一个函数的返回值为某种数据类型的地址值,即指针类型数据,称该函数为指针型函数。 定义指针型函数的格式: 类型说明符 *函数名(参数表); 例:int *a(x , y);main() static float sco
16、re4= ; float *search(); /*search()返回指向实型数据的指针*/ float *p; int i,m ; /* p为指向实型数据的指针*/ scanf(“%d”,&m); printf(“The scores of No.%d are:n”,m); p=search(score,m); /* score为行指针 */ for(i=0;i4;i+) printf(“%5.2ft”,*(p+i);float *search(float (*pointer)4,int n) float *pt; pt=*(pointer+n); return(pt); 3.递归函数调用
17、一个函数的过程中又出现直接或间接地调用该函数本身叫递归。书上的图要牢记,要画图解决!【思想推广】函数是最基础的东西,如果一个程序过于复杂,不如将其分解为一个个简单的函数,再通过嵌套将其串起来。13.链表【思想汇总】链表是C语言中集大成者,不仅涉及到数组,字符串,还有指针,结构公用体,可谓是C语言的究极产物(仅限我们现在所学),掌握链表其实并没有想象中的难,再说上机也不靠,做链表题要像做递归一样图解。下面我写一个比较常见的链表算法供大家参照。【算法语句】#include#include#define N 8struct slist double s; struct slist *next;typ
18、edef struct slist STREC /*这里是为struct slist 取个别名 STREC*/double fun(STREC *h) double max=h-s; while(h!=NULL) if(maxs; /*结构指针指向第一个结构每一个元素,取出最大 h=h-next; 值后,进入下一个结构体*/return max;STREC *creat(double *s) STREC *h,*p,*q; int i=0; h=p=(STREC*)malloc(sizeof(STREC); /*开辟一个动态的结构指针*/ p-s=0; while(is=si;i+;p-nex
19、t=q;p=q; 链表中*/p-next=NULL:return h; /*返回首节点*/outlist(STREC *h) STREC *p; p=h; printf(“head”); do printf(“-%2.0f”.p-s); /*输出各分数*/ p=p-next;while(p-next!=NULL);printf(“nn”);void main() double sN=85,76,56,79,32,78,99,86,max; STREC *h; h=creat(s); outlist(h); max=fun(h); printf(“max=%6.1fn”,max);【思想推广】在做链表题时要分清出哪个是首节点,哪个是尾节点,哪个是是新节点。在生成链表是要返回首节点,在输出链表是要那首节点做实参。在我写的上机程序中也有类似的,可自行参照。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1