C语言学习——数组程序设计举例(顺序、最值、排序、查找、循环访问、字符处理)

C语言学习——数组程序设计举例

一、 一维数组应用举例

1.顺序或逆序访问数组元素

【例1】 用C语言编程输入10个整数,要求逆序打印其中的自然数,例如,输入12,-23,5,0,45,-81,72,56,90,28,程序输出的结果为28,90,56,72,45,5,12
分析: 根据题意,需要定义一个能存放 10 个整数的数组 num 和用于控制下标变化的计数器 i,利用循环,让计数器 i递增,依次输入各个初值,然后再利用计数器 i 递减逆序访问每个数组元素,最后打印其中的非零正数。

 // Description: 输入10 个整数,要求逆序打印其中的自然数。 
#include 
void main( void )
{ 
    short num[10], i ;             
 
    printf("请输入10个整数:");       
    for(i=0; i<10; i++)                     // 顺序输入10个数据 
         scanf("%d,",&num[i]); 
    
    printf("逆序打印其中的自然数:");      
    for(i=9; i>=0; i--)                                //逆序访问各数组元素 
         if(num[i]>0) 
             printf("%d,", num[i]);              //打印正数 
} 

2. 寻找最大值、最小值和它们的位置

【例】 用C语言编程输入10个整数存入数组num,找出其中的最大数和它所在的位置。
分析: 根据题意,必须先定义一个能存放输入的 10 个整数的数组 num、计数器 i,利用循环,让计数器 i从 0 递增到9,依次输入 10 个整数存到 num[i]中。当然,还要定义一个存放最大数的变量 Max、一个存放最大数所在位置的变量 MaxPos。对于查找极值的问题,初值的选取是非常重要的,不能随便定,如果选 0 作为最小值,就无法发现输入数据中比 0 更小的负数。查找极值的算法通常选取数组的起始元素和起始位置作为初值。然后利用计数器 i 从 1到 9,依次用 num[i]和 Max 比较,若 Max

#include  
#define SIZE 10 
void main( void ) 
{ 
    int num[SIZE];    
	int i, Max, MaxPos; 
    printf("Enter 10 integers:\n"); 
    for(i=0; i<SIZE; i++) 
    { 
         printf("第%d个数:",i);  
         scanf("%d",&num[i]); 
    }  
    Max=num[0];   // Max要设置初值
    MaxPos= 0; 
    for(i=1; i<SIZE; i++) 
         if( Max < num[i] ) 
         { 
              Max=num[i]; 
              MaxPos=i; 
         } 
    printf("Maximum value is %d\n", Max); 
    printf("It’s position is %d\n", MaxPos); 
}

3. 排序

1 选择法

排序过程:
(1)首先通过n-1次比较,从n个数中找出最小的, 将它与第一
个数交换—第一趟选择排序,结果最小的数被安置在第一
个元素位置上
(2)再通过n-2次比较,从剩余的n-1个数中找出关键字次小的
记录,将它与第二个数交换—第二趟选择排序
(3)重复上述过程,共经过n-1趟排序后,排序结束

【例】 用C语言编程实现对10个整数按从小到大顺序进行选择法排序,最后输出排序结果。
分析: 根据题意,必须先初始化一个存放了 10 个整数的数组 Num,定义两个计数器 i、j,利用两重循环,让计数器 i 负责扫描 n−1 趟,让计数器 j 在内循环中进行 n−i 次比较。在 i 次循环时, 把第 i 个元素的位置 i 赋予变量 pos。 内循环从 Num[i+1]起一直比到最后一个元素,逐个与位置 pos 对应元素 Num[pos]作比较,将更小元素的位置记录到 pos 中。内循环结束后, pos 对应了最小元素, 如果 i=pos 表示 Num[i]就是最小的, 否则交换 Num[i]和 Num[pos]之值。排好 Num[i]后转入下一轮外循环。对 i+1 以后各个元素排序。最后将排序结果打印出来。

 // Description: 对10个整数按从小到大顺序进行选择法排序
#include 
#define SIZE 10
void main(void)
{
    int Num[SIZE]={12,32,28,45,67,48,18,72,90,68};
    int Pos, tmp, i, j;

    printf("Normal numbers:");
    for(i=0; i<SIZE; i++)
         printf("%d ",Num[i]);
    printf("\n");

    for(i=0; i<SIZE-1; i++)
    {
         Pos=i;
         for( j=i+1; j<SIZE; j++)
               if(Num[j]<Num[Pos])
                   Pos=j;
         if(i!=Pos)
			 tmp=Num[i], Num[i]=Num[Pos], Num[Pos]=tmp;
    }

    printf("Sorted numbers:");
    for(i=0; i<SIZE; i++)
         printf("%d ",Num[i]);
    printf("\n");
}

2 冒泡法(bubble sort)--相邻元素比较交换法

排序过程:
(1)第一趟扫描:从i=1开始,依次比较A[i]与A[i+1] ,若为逆序(A[i]>A[i+1]),则交换其值;依次类推,直至第n-1个数和第n个数比较为止——第一趟扫描使最大的数被安置在第n个元素位置上。

(2)对前n-1个数进行第二趟扫描,结果使次最大的数被安置在第n-1个元素位置。

(3)重复上述过程,最多经过n-1趟扫描后,排序结束

// Description: 对10个浮点数按从小到大顺序进行冒泡法排序。
#include 
#define SIZE 10
void main(void)
{
    float Num[SIZE]={11.2,32.1,25.8,4.5,6.7,4.8,18,27.2,19,6.8}, tmp;
    int i, j;

    printf("Normal numbers:");
    for(i=0; i<SIZE; i++)
         printf("%5.1f",Num[i]);
    printf("\n");

    for(i=0; i<SIZE-1; i++)
    {
         for( j=0; j<SIZE-i-1; j++)
               if(Num[j]>Num[j+1])
                   tmp=Num[j], Num[j]=Num[j+1], Num[j+1]=tmp;
    }

    printf("Sorted numbers:");
    for(i=0; i<SIZE; i++)
         printf("%5.1f",Num[i]);
    printf("\n");
}

4. 二分查找(Binary Search,又称折半查找)

【例 】 用 C 语言编程实现在按从大到小顺序排好序的 15 个整数中查找输入的数 x,如果找到 x,打印其位置,否则输出“未找到 x! ”的提示。
分析: 设数组Num存放按从大到小顺序排好序的SIZE个数,Begin代表查找区间的起点(初值为0)、End代表终点(初值为SIZE-1)

1)Mid代表当前查找区间的中间点位置:
Mid=( Begin + End )/2。
2)若x >Num[Mid] ,则x必定在区间[0,Mid-1]中,
需要将End修正为Mid-1。
3)若x 需要将Begin修正为Mid+1。
4)重复这一过程直至找到x为止。
如果当前查找区间为空(End

注意:二分查找的查找对象是已经排好序的数据。

// Description: 按从大到小顺序排好序的15个整数中查找输入的数x。
#include 
#define SIZE 15
void main( void )
{
    int Num[SIZE]={81,72,68,66,56,48,36,33,22,12,10,9,6,3,1};
    int Begin=0, End=SIZE-1, Mid, x;

    printf("Input x:");
    scanf("%d",&x);
    while( Begin<=End )
    {
        Mid=(Begin+End)/2;
        if(x==Num[Mid])
        {
            printf("It's position is %d \n", Mid+1);
            break;
        }
        if(x<Num[Mid])	Begin=Mid+1;
        else            End=Mid-1;
    }

    if(Begin>End)
        printf("Cann't find it\n");
}

5. 插入

我们经常要插入一个新数到排好序的数据序列中,要求新的序列仍然保持原有顺序。常见的操作还有删除、逆序、合并等。
【例 】 用 C 语言编程实现在按从小到大顺序排好序的 9 个浮点数中插入一个输入的数,要求新的序列仍然保持原有顺序。
分析: 由于要插入一个新数到原数据序列中,我们在初始化一个存放按从小到大顺序排好序的浮点数数组 Num时,数组 SIZE 长度至少要设置成 9+1=10个,这是插入问题的关键所在。最后一个数据元素在初始化时不要赋值。可以将要插入的数存到这个位置上。将它和前面的SIZE−1 个数据依次比较,如果发现Num[i]>Num[SIZE-1],违背了从小到大排列的规律,互换其值。如果比较到最后都没有发现比 Num[SIZE-1]大的数,那就将插入的新数放在最后。

// Description: 在按从小到大顺序排好序的9个浮点数中插入输入的数
#include 
#define SIZE 10
void main( void )
{
    float Num[SIZE]={12,22,33,36,48,56,68,72,81};
    int i; float tmp;

    printf("Normal numbers:");
    for(i=0; i<SIZE-1; i++)
         printf("%3.0f",Num[i]);
    printf("\n");

    printf("Input new number:");
    scanf("%f",&Num[SIZE-1]);
    for( i=0; i<SIZE-1; i++ )
          if( Num[i]>Num[SIZE-1] )
               tmp=Num[i],Num[i]=Num[SIZE-1],Num[SIZE-1]=tmp;

    printf("New numbers:");
    for(i=0; i<SIZE; i++)
         printf("%3.0f",Num[i]);
    printf("\n");
}

6.循环访问数组

循环访问N个元素的数组是指从头依次访问数组的每一个元素到队尾后,在从头开始访问数组。可以设计一个计数器从0递增到N-1依次访问数组的每一个元素,当计数器的值为N时将计数器重新置为0从头开始访问。

经典例题:约瑟夫问题

// Description: 打印约瑟夫(Joseph)环的出圈顺序表。
#include 
#define N 13
#define S  1
#define M  3
void main( void )
{
    short i,pos;
    short Queue[N], j=N;    	//圈中有N个人
    short s=S-1;				//从第s个人开始依次报数
	
    for(i=0; i<N; i++)			//按顺时针方向围坐一圈
		Queue[i]=i;
	printf("%d个人按顺时针方向围坐一圈,从第%d个人开始依次报数,\n"\
		"数到%d的人出圈, 下一个人继续报数,直到所有人出圈为止。\n"\
		"这些人的出圈顺序表是:", N, S, M);
    
	i=0, pos=s-1;
	do			
    {
		pos++;
		if (pos==N)			   				//恰好数到圈尾
            pos=0;
		if (Queue[pos]!=-1)					//数数
		{
            i++;
			if (i==M)			   			//数到M的人出圈
			{
				printf(" %d",Queue[pos]+1);	//打印出圈人
				Queue[pos]=-1;				//出圈
				--j;						//人数减一
				i=0;						//重新计数
			}
		}
	}while(j>0);							//圈中还剩余j人
	printf("\n");
}

二、 二维数组程序举例

【例1】 编程实现指定二维数组的转置。
解题思路: 二维数组的转置是指将一个二维数组行和列的元素互换,存到另一个二维数组中去。

// Description: 将指定二维数组转置。
#include 
void main( void )
{
    int a[2][3]={{1,2,3},
                 {4,5,6}};
    int b[3][2], i, j;

    printf("原数组\n");
    for(i=0;i<=1;i++)
    {
         for(j=0;j<=2;j++)
              printf("%5d",a[i][j]);
         printf("\n");
    }

    for(i=0;i<=1;i++)
            for(j=0;j<=2;j++)
               b[j][i]=a[i][j];

    printf("转置后的数组\n");
    for(i=0;i<=2;i++)
    {
          for(j=0;j<=1;j++)
               printf("%5d",b[i][j]);
          printf("\n");
    }
}

【例2】 编程求指定二维数组中最小元素的值及其位置(行列号)。
解题思路: 这是二维数组的求极值问题。参照一维数组的分析,先初始化一个二维数组Matrix、计数器i、j,还要定义一个存放最小数的变量Min、一个存放最小数所在位置的变量MaxPosi、
MaxPosj。选取数组的起始元素和起始位置作为上述变量的初值。然后利用循环依次用Matrix[i][j]和Min比较,若Min>Matrix[i][j],令Min= Matrix[i][j]。最后打印最小元素的值及其位置。

// Description: 求指定二维数组中最小元素的值及其位置。
#include 
void main( void )
{
    int Matrix[3][4]={{  1,    2,  3, 4},
                      {  9,    8,  7, 6},
                      {  -10, 10, -5, 2}};
    int i, j, MinPosi, MinPosj, Min;

    Min=Matrix[0][0]; MinPosi=0; MinPosj=0;
    for(i=0; i<3; i++)
         for(j=0; j<4; j++)
              if( Min>Matrix[i][j] )
              {
                   Min=Matrix[i][j];
                   MinPosi=i;
                   MinPosj=j;
              }

    printf("Min=%d, row=%d, colum=%d\n", Min,
          MinPosi, MinPosj );
}

三、字符串应用举例

【例1】 不用strcmp函数编程实现对输入两个字符串的比较。
(字符串处理)
分析: 首先要根据题意定义两个一维字符数组,接受输入的两个字符串。然后借助计数器 i 从左向右对两个字符串第 i 个字符逐个比较其 ASCII 码值,直到存在差异或遇到字符串结束符NULL 为止,并由两个字符 ASCII码值差的三种情况显示相应比较结果。

 // Description: 不用strcmp函数,实现对输入两个字符串的比较。
#include 
void main( void )
{
    char string1[20], string2[20];
    short i; 
 
    printf("输入两个字符串:\n");
    gets(string1);
    gets(string2);
 
    for (i = 0; string1[i] == string2[i]; i++) 
         if (string1[i] == '\0') 
               break; 

    if( string1[i] - string2[i] >0 )
		printf("%s>%s\n", string1, string2);
	else
		if( string1[i] - string2[i] ==0 )
			printf("%s==%s\n", string1, string2);
		else
			printf("%s<%s\n", string1, string2);
}

【例2】 不用itoa函数,编程实现将一个输入的整数转换为字符串。(字符转换)
分析: 库函数 atoi可以把一个数字字符串转换成对应整数,而 itoa 可以将一个输入的整数转换为字符串。根据题意定义一个整型变量 Num存放输入的整数,一个一维字符数组 Str,借助计数器 i从右向左求 Num逐位数字, 并将其转换成 ASCII字符, 直到处理完符号位为止,将所得字符串逆序并显示即可。

 // Description: 不用库函数,将一个输入的整数转换为字符串。
#include 
void main( void )
{
    char Str[20], tmp;
    short Num, i, j, Sign; 
 
    printf("输入一个整数:");
	scanf("%d", &Num);
 
	if((Sign=Num)<0)//记录负号
        Num=-Num;	//num取绝对值
	i=0;
	do{
        Str[i++]=Num%10+'0';//取下一个数字
	}while ((Num/=10)>0);//删除该数字
	
	if(Sign<0)
        Str[i++]='-';
	Str[i] = '\0'; //生成的数字是逆序的,所以要逆序输出
	for (j = i-1, i = 0; i < j; i++, j--) 
		tmp = Str[i], Str[i] = Str[j], Str[j] = tmp; 
	printf("The string is \"%s\".\n", Str );
}

【例 3】 编程实现将一个输入的口令字符串加密。
(基于字符的加密、解密)

字符串加密是指按照一定的规律将代表秘密的字符串,如口令,变换成没有意义的内容。加密过的文字,即使被别有用心的人得到,也无从得知里面的内容。合法用户则可以根据对应的规律将密文还原成原文使用。
字符串加密、解密的方法有很多,简单一点的是直接对字符加上或减去一个数,从而将字符变成另一个数。更进一步是将这个数换成一串复杂的密文(密钥) ,或干脆使用一张字符变换对照表……

// Description: 将一个输入的口令字符串加密。
#include 
void main( void )
{
    char Str1[20], Str2[20];
    unsigned short i; 
 
    printf("输入一个口令:");
	scanf("%s", Str1);
 
	i=0;
	while (Str1[i])
	{
        Str2[i]='z'-Str1[i]+'a';//-1
		i++;
	}	
	Str2[i]='\0';

	printf("The changed string is %s\n", Str2 );
}

【例4】 已知10 名同学的姓名和考试成绩,编程实现按姓名的字典顺序将其递增排序。
本题首先要根据题意初始化一个二维字符数组Names[10][10]存放10 名同学的姓名、一个一维数组Scores[10]存放10名同学的考试成绩,然后借助冒泡法、选择法排序算法的思想对其排序,需要注意的是:
首先,字符串不能直接比较大小,需要调用strcmp 函数,交换顺序时要调用strcpy函数,为此需要嵌入string.h。
其次,在交换姓名的同时,必须将对应的成绩也要进行交换。
将上述思路转换成C源程序:

// Description: 编程将10名同学的姓名和考试成绩按姓名递增排序。
#include 
#include 
void main( void )
{
    char Names[10][10]={"zhang","wang","li","zhao","qian","sun","wan","zao","wu","zheng"}, NameTmp[10];
	short Scores[10]={95,74,83,90,66,89,70,92,73,86}, ScoreTmp;
    unsigned short i, j; 
 
	for(i=0; i<10; i++)
		for( j=0; j<10-i-1; j++)
			if(strcmp(Names[j], Names[j+1])>0)
			{
				strcpy(NameTmp, Names[j]);
				strcpy(Names[j], Names[j+1]);
				strcpy(Names[j+1], NameTmp);
				ScoreTmp=Scores[j];
				Scores[j]=Scores[j+1];
				Scores[j+1]=ScoreTmp;
			}

	printf("The shorted data is :\n");
	for(i=0; i<10; i++)
		printf("%s\t%d\n", Names[i], Scores[i]);

}

你可能感兴趣的:(C语言基础知识,算法)