这周我对指针进行了更加深入的学习,明白了指针和数组之间是有着千丝万缕的关系的,数组变量其实可以看作一个const的指针变量。而指针使用const会出现两种情况,第一种是对指针本身即指针所指的地址const(上面说数组可以看成cons的指针就是这种);第二种是对指针所指的变量const(这里所指变量const是指无法通过指针修改变量,但这个变量的本身其实是可以修改的)。第一种const是这样创建的 const int *p或者int const* p ,第二种则是 int *const p。当然,如果这样创建数组 const int *const p 则指针既不能更改地址,也不能修改指向地址上的值。
我们平时对于指针使用是比较少的,但是指针其实也是有一些妙用的。例如,它可以类似的是一个函数返回多个值,代码如下:
void minmax( int a[] , int len , int *min , int *max)
{
int i ;
*min = *max = a[0];
for( i = 0 ; i <= len - 1 ; i++){
if( a[i] < *min ){
*min = a[i];
}
if( a[i] > *max ){
*max = a[i];
}
}
}
这样一个函数就能同时找出一个数组中的最大值和最小值。
这周除了指针以外,我还对算法进行了学习,但是因为C语言还没有学好,在算法的学习中也是遇到了不少麻烦,也并没有去接触一些难度大的算法,而是找了一些简单的算法题进行解答。
例如上次程序设计大赛上的最大子序列和问题,我当时是这样写的:
#include<stdio.h>
int main(void){
int thissum,maxsum,i,j,N;
scanf("%d",&N);
int A[N];
for( i = 0 ; i <= N - 1 ; i++)
{
scanf("%d",&A[i]);
}
maxsum = thissum = 0
for( i = 0 ; i <= N -1 ; i++){
thissum = 0;
for( j = 0 ; j <= N - 1; j++){
thissum += A[j];
if ( thissum > maxsum){
maxsum = thissum;
}
}
}
return 0;
}
很简单,就是将所有的连续子数列全部遍历一遍,找出最大的序列。但是,这样写运算量会很大,当数组元素到一定大小后就会导致程序崩溃,我参考资料后看到了这样一个代码,将计算量降到了最小。
#include<stdio.h>
int main(){
int N,i,maxsum,thissum;
scanf("%d",&N);
int A[N];
for( i = 0 ; i <= N - 1 ; i++)
{
scanf("%d",&A[i]);
}
thissum=maxsum=0;
for( i = 0; i <= N - 1; i++ )
{
thissum += A[i];
if(thissum > maxsum)
maxsum = thissum;
else if(thissum < 0 )
thissum = 0;
}
printf("%d",maxsum);
return 0;
}
这个算法的关键在于,当当前总和小于0时,就把0赋给当前总和,因为当前面的和为负,它势必会减小后面的数的总和,所以直接把前面的数全部舍弃,从下一个数开始。
在做算法题的时候,我也是遇到了不少的问题,因为一些看似简单的算法的题上,往往涉及很多强制的格式要求,例如:
#include<stdio.h>
int main(){
int length,width,height,n,i;
while(scanf("%d",&n) && n != -1){
int a[n];
char name[n][9];
for( i = 0 ; i <= n-1; i++){
scanf("%d %d %d",&length,&width,&height);
a[i] = length*width*height;
scanf("%s",&name[i]);
}
int max = 0,min = 250*n,x,y;
for( i = 0 ; i <= n-1 ; i++){
if(max <= a[i]){
max = a[i];
x = i;
}
if(min >= a[i]){
min = a[i];
y = i;
}
}
printf("%s took clay from %s.\n",&name[x],&name[y]);
}
return 0;
}
这是在计蒜客上的题目,名字叫“泥塑课”,题目本身不难,但是敲出这串代码却是花费了我不少时间,先是去学习了字符串的知识,又去了解了while上的一个妙用,即这句代码 while(scanf("%d",&n) && n != -1)。
在例如:
#include<stdio.h>
int main(){
long long a;
while( (scanf("%lld",&a) ) != EOF){
double x = 10000;
while(x*x - a > 0.1 || x*x-a < -0.1){
x = x - ( x*x - a ) / (2 * x) ;
}
printf("%d\n",(int)x);
}
return 0;
}
这是一个简单的用牛顿迭代法求根号x的算法,但是题目上要求的输出必须是去尾整数、EOF结束以及所能计算数字的大小却让我花费了大量的时间,先是去搜资料学习EOF文件结束符怎么使用,然后发现这题上不论用整型还是浮点型都无法得到题目要求的结果,因为整型会导致迭代时死循环,而浮点更是不行,于是又学习了如何强制转换变量的类型,最后在提交时,又发现有一组数据通过不了,想了一会才意识的这可能是数据太大,需要将 int 改为 long long int。
总之,通过这周对于对算法的学习,我不仅对算法有了初步了解,也是对解决算法题上的基础知识有了更好的掌握。