C语言二级常考算法

常考题型归纳:

一:数值类

题型1:素数问题

素数:只能被自己与1整除的数,最小的素数是2,比如3,5,7等都是素数
算法:任意输入一个数判断是否是素数

#include <stdio.h>   
#include <conio.h>
int prime(int n)       // 实现判断素数函数          
{for(int k=2;k<n;k++)           //核心程序
  {if(n%k==0) return 0;}
  return 1;}
void main()
{int n;
 scanf(%d”,&n);
  if(prime(n))
    printf(%s”,”yes”);
  else
    printf(%s”,”no”);
  getch();  clrscr();        //清屏}

题型2:整数拆分

整数拆分是将整数n的每一个数取出,在取数的过程中,不断使用”%”和”/”运算符号
算法:输入整数n,求出n的各个位数相加之和,如输入3476,结果为20

#include <stdio.h>
main()
{
  int n, x, sum=0;
  scanf(%d”,&n);
  while(n!=0)              //此while程序为关键
  {x=n%10;
sum+=x;
n=n/10;}
   printf(%d\n”,sum);}

题型3:回文数(反读与正读相同的数,比如121,313等)

编程题:
(1)在给定范围内查找k使得用公式k^2+k+17生成的整数满足以下条件:该数的十进制表示中低3位数字相同,去掉低3位后的整数是回文数。例如,当k=461时用公式生成的整数是212999,该数满足所给条件。
【编程要求】
1.编写函数int findnum(int n1,int n2,long a[][2])实现以下功能:k依次取n1~n2范围内的每个整数,分别用每个k及公式k^2+k+17生成整数y,若y满足给定条件,则将k值及y值保存到a指向的数组中,函数返回a数组中k的个数。
2.编写函数main实现以下功能:声明二维数组a和变量n1、n2,输入两个整数并保存到n1、n2中,用 n1、n2及a数组作实参调用findnum函数,按所给格式输出a数组中的数据到屏幕及文件myf2.out中。最后将考生本人的准考证号输出到文件myf2.out中 。
【测试数据与运行结果】
输入:n1=1,n2=10000
输出:k number
461 212999
586 343999
3839 14741777

#include  <stdio.h>
int findnum(int n1,int n2,long a[][2])
{  int i=0,j;
   long x1,x2,x3,y,k;
   for(k=n1;k<=n2;k++)
   {y=k*k+k+17;
    x1=x2=y/1000;x3=0;
    while(x1>0)                    //本while循环将x1逆序变为x3
    {x3=x3*10+x1%10;x1=x1/10;}
     if(x2==x3&&y%10==y/10%10&&y%10==y/100%10)  //判断是否是回文数同时低3位数是相同的
     {  a[i][0]=k;a[i++][1]=y;}
    }
    return i;    
  }
  main()
  {int i,j;long a[10][2],n1,n2;  FILE *fp;
   fp=fopen("Myf2.out","w");
   scanf("%d%d",&n1,&n2);
   j=findnum(n1,n2,a);
   printf("\n k\t number");
   for(i=0;i<j;i++)
prinff("\n%ld\t%ld",a[i][0],a[i][1]);
   fprintf(fp,"\n k \t number");
   for(i=0;i<j;i++) 
fprintf(fp,"\n%ld\t%ld",a[i][0],a[i][1]);
   fprintf(fp,"\n My exam number is :0112400123");
   fclose(fp);getch();
  }

题型4:排序问题

(1)简单选择排序法
规律:(1)首先将第一个数a[0]与后面的每一个元素比较,比较时将比a[0]小的数和a[0]交换
(2)接着在除了a[0]以外的所有元素中,将a[1]与其之后的每一个元素比较,找到次小数放在a[1]位置。
(3)重复这个过程a-1遍,最后构成递增序列

#include <stdio.h>
void sort(int a[ ],int n)       //简单选择排序法
{ int k;
  for(int i=0; i<n-1; i++)
  {k=i;
   for(int j=i+1;j<n;j++)
    if(a[k]>a[j])  k=j;
   if(k!=i)
    {temp=a[i];  a[i]=a[k];  a[k]=temp;}}
  }

void print(int b[ ], int n)
{for( int i=0; i<n; i++)
     printf(%6d”, b[i]);}
void main()
{int a[ ]={6,3,1,2,5,0,9,3,7,6};
  sort(a,10);
  print(a,10);
}
 (2)冒泡排序法:
冒泡排序:(1)始终比较的是相邻数字
(2)每趟排序后,最大数移到后面,最小数移到前面,注意与快速排序法的区别。
编写基于冒泡排序法的排序函数对10个整数进行升序排序
#include <stdio.h>
void sort(int a[ ], int n)
{int temp;
  for( int i=0; i<n-1; i++)
  {for( int j=0; j<n-i; j++)
    {if(a[j]>a[j+1])
      {temp=a[j];  a[j]=a[j+1];  a[j+1]=temp;}}
  }}
void print(int b[ ], int n)
{for(int i=0; i<n ; i++)
  {printf(%6d”, b[i]);}
}
main()
{int a[10]={6,7,4,10,2,5,9,8,3,1};
 sort(a,10);
 print(a,10);}

(3)插入排序法:
插入排序法是将数据一个一个地插入到已经有序的数列中,并保证每插入一个数后数列仍然有效。
插入排序的思想是:1先确定n个数x插到数组中的位置k,因为原本的数组有序,所以从第一个起到n-1个为止逐个比较,一直遇到比x大的数为止,这个位置就是x插入的位置
2确定应插入到位置k后,后面的元素要向后顺移一个位置以空出一个位置放入x
算法实现:

#include <stdio.h>
#include <conio.h>
void main()
{int i, n, x;
 void insert(int *, int , int *);
 int a[ ]={-3,2,6,9,14,19};
 n=6;
 scanf(%d”,&x);
 insert(a,x,&n);
 for( i=0; i<n; i++)
    printf(%d”, a[i]);}

void insert(int *b, int y, int *m)                   //插入排序法
{int i,j, k;
 for(i=*m-1; i>=0; i--)
  {if(y<*(b+i))
    *(b+i+1)=*(b+i);
else
    break;
   }
*(b+i+1)=y;  (*m)++;
}

历年真题

投要求合并两个字符串。

【编程要求】
1.编写函数void fun(char *a,char *b,char *c),其功能是先将b指向的字符串逆存放,然后按a[0],b[0],a[1],b[1],…的顺序合并a字符串和b字符串到c指向的数组中,a或b中剩余字符拼接在c数组的尾部。
2.编写main函数,声明三个一维数组s1、s2和s,接收键盘输入的两个字符串并保存数组sl和s2中,调用fun函数对s2字符串做逆序变换,再合并sl字符串和s2字符串到s数组中。将合并后产生的数组s中的字符串输出到屏幕
【测试数据与运行结某】
测试数据:s1字符串为"abcdefg",s2字符串为"ABCD"
运行结果:aDbCcBdAefg

#include<stdio.h>
#include<string.h>
void fun(char *a,char *b,char *c)
{   int i,j;
    char ch;
    i=0;j=strlen(b)-1;
    while(i<j)              //本while循环实现逆序
    { ch=b[i];b[i]=b[j];b[j]=ch;
      i++;  j--;
    }
    while(*a || *b)        //本while循环实现将a与b放到c里面
    {if(*a){*c=*a;c++;a++;}
     if(*b){*c=*b;c++;b++;}
    }
    *c='\0';
  }  
  void main()
  {  
    char s1[80],s2[80],s[200];
    prinff("\nEnter sl string:");
    gets(s1);
    prinff("\nEnter s2 string:");
    gets(s2);
    fun(sl,s2,s);
    prinff("\nThe resuIt is:%s\n",s);
   }

二:字符串类

题型1:字符串与整数问题

例题:编写一个函数,将一个数字字符串转换为一个相应的整数
例如:输入字符串”-1234”,则函数把它转换为整数-1234

#include <stdio.h>
#include <string.h>
long fun(char *p)
{int i=1;
 long n=0;
 if(*p==-) {p++;i=-1;}
 else if(*p==+) p++;
 while(*p>=0&& *p<=9)                //关键转换算法
n=n*10+*p++-0;
 return n*i;
}
void main()
{
   fun(-1234);
}

题型2:字符串的子串问题

例题:函数fun的功能是:求出在字符串中最后一次出现子字符串的位置,通过函数值返回,若未找到,则函数值为-1

int fun(char *str, char *t)
{char *p,*r,*s=str;
 int a=-1;
while(*s)
{p=s;
 r=t;
 while(*r)
  if(*r==*p) {r++;p++}
     else break;
if(*r==’\0)  a=s-str+1;
s++;
}
 return a;
}

void main()
{int p;
 char s[100],t[100];
 scanf(%s”,s);  scanf(%s”,t);
 p=fun(s,t);
 printf(“The result is:%d”,p);
}

题型3:出现次数问题

函数void fun(char *tt, int *pp)的功能是:统计在tt所指字符串中’a’—‘z’26个字母各自出现的次数,并依次放在pp所指数组中,要求只统计小写字母
例如:当输入字符串”abcde”后,程序的输出结果应该是
11 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

#include <stdio.h>
#include <string.h>
void fun(char *tt, int *pp)
{
   int i,k=0;
   char c;
   for(c=’a’;c<=’z’;c++)
   {pp[k]=0;
for(i=0;i<strlen(tt);i++)
   if(tt[i]==c)  pp[k]++;
k++;
   }
  }
void main()
{char aa[1000];
 int bb[26];
 scanf(%s”,aa);
 fun(aa,bb);
 for(k=0;k<26;k++)  printf(%d”,bb[k]);
 printf(“\n”);
}

三:二维数组问题

题型1:最值问题与矩阵转换
例题:随机输入五个数,判断最大值

#include <conio.h>
#include <stdio.h>
main()
{int  a[5],max,i;
  for(i=0;i<5;i++)
     scanf(%d”, &a[i]);
  max=a[1];
  for(i=0;i<5;i++)
if(max<a[i])   /*这边为判断最大数的关键一步,如果把max换成max>a[i]就变成求最小值了*/
     max=a[i];
printf(%d”,max);
getch();    clrscr();    //清屏} 

历年真题:
改错题(对数值处理试题)
【程序功能】
已知x数组中存储的n阶矩阵有一个鞍点(鞍点是指该位置上的数是所在行的最大数。同时也是所在列的最小数),程序实现将矩阵中鞍点所在列移动到最右侧。
【测试数据与运行结果】
测试数据;
1 3 2 0
4 6 5 -1
7 9 8 0
-1 l0 3 2
运行结果;
An dian;a[0][1]
1 2 0 3
4 5 -1 6
7 8 0 9
-1 3 2 10
【含有错误的源程序】

    #include<stdio.h>
    #define N=4  
    void exchange(int a[ ][N])
    {int i,j,k,f,t,m,mj;
    for(i=0;i<N;i++)               
    {m=a[i][0];  mj=0;f=1;
     for(j=0;j<N;j++)               //寻找所在行的最大值下标
       if(a[i][j]>m)
        {m=a[i][j];  mj=j;}
       for(k=0;k<N&&f;k++)     // 判断是否符合在列中也是最小的
         if(a[k][mj]>m)
            f=0;
       if(k>=N)break;
    }
    if(f)
    {printf("An dian;a[%d][%d]\n",i,mj);
     for(i=0;i<N;i++)           //鞍点所在列移动到最右侧
     {  t=a[i][mj];
        for(j=mj;j<N-1;j++)
          a[i][mj]=a[i][mj+1];
        a[i][N-1]=t;
     }
    }
   }
void main()
{int x[N][N]={{1,3,2,0},{4,6,5,-1),{7,9,8,0),{-1,10,3,2}},i,j;
  for(i=0;i<N;i++)
  {for(j=0;j<N;j++)
    printf("%3d",x[i][j]);
   printf("\n");
  }
  printf("\n");
  exchange(int x[N][N]);
  for(i=0;i<N;i++)
  {for(j=0;j<N;j++)
    printf("%3d",x[i][j]);
   printf("\n");
   }
}

本程序四个错误点:
(1)#define N=4 修改为:#define N 4 (2)if(a[k][mj]>m) 修改为:if(a[k][mj]<m)
(3)a[i][mj]=a[i][mj+1] 修改为:a[i][j]=a[i][j+1] (4)exchage(int x[N][N])修改为:exchange(x)
题型2:穷举法
穷举法的基本思想是不重复、遗漏的列举所有可能情况,从中寻找满足条件的结果。
例题:输出所有的水仙花数。水仙花数是一个三位数,且这个三位数的每一位的立方和等于该数。如153=13+53+3^3

#include <stdio.h>
void main()
{int i,j,k,t;                                 
 for(i=1;i<=9;i++)                         //实现百位数,三个for实现了循环900次
  for(j=0;j<=9;j++)                      //实现十位数    
    for(k=0;k<=9;k++)                   //实现个位数, 
    { t=i*100+j*10+k;
      if(i*i*i+j*j*j+k*k*k==0)
        printf(%d”,t);
   }
}
}

题型3:字符处理次数试题

改错题三:
程序功能:
函数mergeu的功能是:合并两个字符集合为一个新集合,每个字符串在新集合中仅出现一次,函数返回新集合中字符串的个数
[测试数据与运行结果]
测试数据:
s1集合{“while”,”for”,”switch”,”if”,”continue”}
s2集合{“for”,”case”,”do”,”else”,”char”,”switch”}
运行结果:
while for switch if break continue case do else char
[含有错误的源代码]

#include <stdio.h>
#include <string.h>
int merge(char s1[ ][10],char s2[ ][10],char s3[ ][10],int m,int n)
{int i,j,k=0;
 for(i=0;i<m;i++)
   s3[k++]=s1[i];
 for(i=0;i<n;i++)
{for(j=0;j<m;j++)
   if(strcmp(s2[i],s1[j]))
      break;
   if(j>m)
     strcpy(s3[k++],s2[i]);
}
return k;
}

void main()
{int i,j;
 char s1[6][10]={while,for,switch,if,break,continue},
s2[6][10]={for,case,do,else,char,switch},s3[20][10];
j=merge(s1[][10],s2[][10],s3[ ][10],6,6);
for(i=0;i<j;i++)
  printf(%s “,s3[i]);
}	

错误点为:
(1)s3[k++]=s1[i] 修改为:strcpy(s3[k++],s1[i]);
(2) if(strcmp(s2[i],s1[j])) 修改为: if(strcmp(s2[i],s1[j])==0)
(3) if(j>m) 修改为: if(j>m-1)
(4) merge(s1[][10],s2[][10],s3[ ][10],6,6); 修改为: merge(s1,s2,s3,6,6);

分类汇总求平均值,函数sort_aver的形参a指向的二维数组(简称a数组)第一列元素的值代表类别,a数组已按第一列的值从小到大有序排列,sort_aver函数对a数组的n行元素中第一列元素值相同的所有行按列求平均值,并将类别值和除第一列外的各列平均值依次保存到b指向的数组
含有错误的源代码:

#include <stdio.h>
int sort_aver(int a[ ][3],n,b[ ][3])
{int i,j,k=0,c[10];
 for(i=0;i<3;i++)  b[0][i]=a[0][i];
 c[0]=1;
 for(i=1;i<n;i++)
 {  if(b[k][0]==a[i][0])
      {for(j=1;j<3;j++)
         b[k][j]+=a[i][j];
       c[k]++;
      }
 else
 {c[++k]=0;
     for(j=0;j<3;j++)
        b[k][j]=a[i][j];
 }
 }
 for(i=0;i<=k;i++)
   for(j=1;j<3;j++)
     b[i][j]/=c[i];
  return k;
}

void main()
{int x[10][3]={{1,3,3},{1,1,3},{2,3,5},{3,5,4},{3,3,6}},i,j,n;
 n=sort_aver(x,5,b);
 for(i=0 ;i<n ;i++)
 {for(j=0 ;j<n ;j++) printf(%3d “,b[i][j]);
  printf(“\n”);
}
}

错误点:
(1) ort_aver(int a[ ][3],n,b[ ][3]) 修改为: int sort_aver(int a[ ][3],int n,b[ ][3])
(2)c[++k]=0; 修改为:c[++k]=1; (3) return k 修改为:return ++k;
(4)在int x[10][3]={{1,3,3},{1,1,3},{2,3,5},{3,5,4},{3,3,6}},i,j,n;增加 int b[3][3];

三:结构体类试题

改错题1:
[程序功能]
输入两个正确日期且年份在1900-9999范围内,计算并输出两个日期之间间隔的天数,例如:2008-8-1和2009-8-1之间间隔的天数为365
提示:能被4整除并且不能被100整除的年份是闰年,能被400整除的年份也是闰年,其他年份则是平年
[测试数据与运行结果]
显示:first date:
输入:1980-2-1
显示:second date:2009-8-1
输出:10774 days
[含有错误的源程序]

#include <stdio.h>
#define leap(int y) ((y)%4==0 && (y)%100!=0||(y)%400==0)
struct d
{int y,m,d;};
int days(struct d d1,struct d d2)
{int mon[2][13]=
  {{0,31,28,31,30,31,30,31,31,30,31,30,31},
   {0,31,29,31,30,31,30,31,31,30,31,30,31}};
 int i; long td=0;
 for(i=d1.y;i<d2.y;i++)          //判断是闰年还是平年然后将天数相加
   td=leap(i)?366:365;
 for(i=1;i<d1.m;i++)            //减去初始年份中月份的天数
   td-=mon[leap(d1.y)][i];
 td-=d1.d-1;
 for(i=1;i<d2.m;i++)            //加上最后年份中月份天数
  td+=mon[leap(d2.y)][i];
 td+=d2.d-1;
 return td;
}

void main()
{struct d d1,d2;
 long td;
 printf("first date:");
 scanf("%d-%d-%d",d1.y,d1.m,d1.d);
 printf("second date:");
 scanf("%d-%d-%d",&d2.y,&d2.m,&d2.d);
 td=days(&d1,&d2);
 printf("%lddays",td);
}

四个错误点为:
(1) #define leap(int y) 修改为:#define leap(y)
(2) td=leap(i)?366:365; 修改为: td+=leap(i)?366:365;
(3) scanf("%d-%d-%d",d1.y,d1.m,d1.d); 修 改为 : scanf("%d-%d-%d"&,d1.y,&d1.m,&d1.d);
(4) td=days(&d1,&d2); 修改为: td=days(d1,d2);
其他常见算法:
(1)累加与累乘
实现1+2+3+4+5+6+7+8+9+10

main()
{ int sum,i;
 sum=0;
 for(i=1; i<=10;i++)
 {sum=sum+i}
}  

实现123456789*10

main()
{int sum,i;
 sum=1;
 do
{sum=sum*i; i=i+1;
}while(i<=10)
}

(2)交换位置
a=5, b=8,实现a与b交换数值

#include <conio.h>
main()
{int a,b,c;
 scanf(%d %d”,&a,&b);
c=a;a=b;b=c;
printf(“a=%d b=%d”,a,b);
getch();
}

(3)递推法:
递推的关键是通过前一个数值推导出后面一个数值
例题:已知某数列的前五项为1,1,2,3,5,请找出规律并求出其后的10项
解题:规律为第一项加第二项等于第三项,第二项加第三项等于第四项,以此类推1+1=2, 1+2=3,2+3=5

#include <stdio.h>
main()
{int  t[15]={1,1,2,3,5};
 int i,j;
 for(i=5;i<15;i++)
 {t[i]=t[i-1]+t[i-2];     //实现了第三个数等于第一个数加第二个数}
  for( i=0;i<14;i++)
  {printf(%d”,a[i]);}
}

(5)递归法:
在调用一个函数过程中又出现直接或间接的调用该函数本身。递归与递推非常相似,递归是自己调用自己。是很重要的算法
例题:求n的阶乘 即n!

#include <stdio.h>
void main()
{float  fac(int n);
  int n;float x,y;
  printf(“input an integer number:);
  scanf(%d”,&n);
  y=fac(n);
  printf(%d!=%10.0f\n”,n,y);
}

float  fac(int n)
{float f;
  if(n<0)
    printf(“n<0,dataerror!);
  else
 if(n==0||n==1)
f=1;
   else
     f=fac(n-1)*n;
return (f);
}
}

(6)求最大公约数
最大公约数:两个数最大的约数

int fun(int a,int b)
{ int r,t;
 r=a%b ;
 while(r !=0)
 {a=b ;b=r ;r=a%b ;}
 return b;
}
void main()
{ int num1,num2;
  scanf(%d%d”,&num1,&num2);
  a=fun(num1,num2);
  printf(%d”,a);
}

(7)迭代法
迭代法是用计算机解决问题的一个基本方法,它利用计算机运算速度快,适合做重复性操作的特点,让计算机对一组指令重复执行。
例题:设方程为4xx-3*x-7=0,给出不精确的初始根x0=2,利用公式:xn+1=xn-f(x0)/f’(xn) n=0,1,2…求出方程的近似根,直到|xn+1-xn|<0.00001。

#include <stdio.h>
#include <math.h>
main()
{float x0,x1;
  x0=2;
  do
  {x1=x0;
x0=x1-(4*x1*x1-3*x1-7)/(8+x1-3);
 }while(fabs(x0-x1)>0.00001);
printf(%f”, x0);
}

在本式中,x0是迭代变量,从最初的x0=2一步步的计算出新值并将老值置换。

改错题常见语法错误:
(1)缺少包含头文件
(2)宏定义出错:#define ,如#define N 3; 应该是 #define N 3 没有;号
(3)主函数中缺少函数声明
(4)从主函数调用子函数时参数数组出错 (是常见错误)
(5)对字符型二维数组赋值用strcpy,而不是用= (常见错误)
(6)for或do循环结束条件问题
(7)定义二维数组出错
(8)=与的区别
(9)strcmp错,比较两个字符串时应该用strcmp不能用

(10) 对变量初始化错误,如int j,如果变量没有初始化默认是随机数,所以int j=0这样是标准写法
(11)用scanf函数给变量赋值时,变量前需要加&
(12)如果函数中出现return说明函数一定不是void类型

  • 6
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值