【C语言】数组的强化训练(详细讲解+源码展示)

简介: 笔记

一维数组


首先简单回顾一下,一维数组是只有一个下标的数组,它用来表示一组具有相同类型的数据,在变量空间中其内存连续,我们可以使用下标去进行访问内部元素。


一维数组的最值

第一个想为大家介绍下一维数组的最值问题,我们在平时训练的时候经常会碰到一种类型的题目,就是给你一个数组,让你去输出数组之中的最大值或者其中的最小值,那么我们就来解决这个问题。


首先,我们要知道如果我们想要得到数组中的最大值或者最小值,我们就要进行比较。问题在于我们在数组中怎么去进行比较呢?


我们在这里运用遍历一遍数组的方法,先设定一个数为我们的目标数,这个目标数我们可以取数组第一个元素;之后,我们从第二个元素去遍历数组,让后面的元素均与目标数相比,如果我们想要寻找最大值,我们就当元素比目标数大的时候,更新一下目标数,也就是让目标数等于当前元素,然后我们再继续的遍历,这样遍历到结束的时候,我们的目标数也就是数组中元素的最大值了;同理可得,如果我们想要得到最小值,就当目标数大于当前元素的时候,更新一下目标数即可,这样当循环结束之后我们就可以得到数组元素中的最小值了。


#include <stdio.h>
int main()
{
  int a[] = {  1, -2, 3, 4, 5, -6, 8, -8, -9, 7 } ;  //定义一个数组,同时初始化所有成员变量
  int i ;
  int max = a[0] ;  //定义我们最大值目标数 
  int min = a[0] ;  //定义我们最小值目标数 
  /* 
  sizeof(a)表示数组a大小, sizeof(a[0]表示数组中一个元素大小 
  因为一个数组中所有的元素大小均相等, 
  所有我们用数组大小除以元素大小就可以得到数组长度了
  所以 sizeof(a) / sizeof(a[0] 就是数组a的长度了 
  */ 
  for (i = 1; i < sizeof(a) / sizeof(a[0]); i++)  //从第二个元素向后循环 
  {
  if (a[i] > max)  //当元素比最大目标数大的时候 
  {
    max = a[i];  //更新最大目标数 
  }
  if(a[i] < min)  //当元素比最小目标数小的时候 
  {
    min = a[i] ;  //更新最小目标数 
  }
  }
  //正常输出 
  printf("数组中最大值为:%d\n", max) ;
  printf("数组中最小值为:%d\n", min) ; 
  return 0;
}

运行结果:

1.png



一维数组的逆置

第二个知识点就为大家讲解一下一维数组的逆置问题,这种题目的大意大概是,给你一个一维数组,你要将一位数组里面的数字去逆置,当然你可能会说,那我们利用for循环从最末的下标楷书输出不就可以了嘛;这种想法确实不算错,但是我们这里如果不按顺序从头到尾输出了怎么办,如果我么你要求输出单个的元素该怎么办呢,所以在这里我们的要求是将数组下标对应的元素去改变逆置了,不是一个我们单纯意义上输出时看到的逆置。


对于这个题目我为大家提供一个思路,首先我们应该知道数组的守下标是0,尾下标应该是我们的(数组长度-1),然后我们设定两个变量,两个变量的初始值就是首尾下标,然后我们利用这两个变量循环,让两个变量从两边向中间移动,每移动一格我们就将两个下标所对应的元素进行交换,这样当两个下标移动到中间时,我们的数组也就逆置完成了。


对于我们利用两个变量循环,我在这里提出两种方法:分别是while循环和for循环 。


for循环:


for(i=0, j=sizeof(a) / sizeof(a[0]) -1; i<j; i++, j--)
while循环:
int i = 0 ;
int j = sizeof(a) / sizeof(a[0]) -1 ;
while (i < j)

我们观察一下这两种形式,发现其有很大的相似点,i和j的值我们都要声明,并且我们在判断退出条件的时候都是i<j ,很容易理解,因为当i>j的时候,两个下标就已经超出中间点了,就不需要再去交换元素了;当 i = j 的时候我们两个下标指的内容是相同的,我们没有必要去交换其元素,所以综合来看,我们使用 i<j 作为判断条件即可;


不知道你注意到没有,在for循环中我们有一个 i++ ; j-- ; 所以我们在进行while循环的时候我们就需要在循环内部添加上这两个语句。


我们在进行交换元素的时候,只需设置出一个临时的同类型变量去暂时储存一个变量即可。


tmp = a[i];  
  a[i] = a[j];
  a[j] = tmp;

所以通过上面的讲解,不知道大家有没有发现,其实我们所学习的那么多循环是相通的,我们在平时使用的时候是可以相互转换的,只不过有时候使用某种循环会比较方便一些。


#include <stdio.h>
int main()
{
  int a[] = {  1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//定义一个数组,同时初始化所有成员变量
  int i = 0;  //头下标 
  int j = sizeof(a) / sizeof(a[0]) -1;  //尾下标 
  int tmp; 
/* 
  for(i=0, j=sizeof(a) / sizeof(a[0]) -1; i<j; i++, j--)
  {
  tmp = a[i];
  a[i] = a[j];
  a[j] = tmp;
  } 
*/ 
  while (i < j) //判断条件 
  {
  tmp = a[i];  //进行元素交换 
  a[i] = a[j];
  a[j] = tmp;
  i++;
  j--;
  }
  for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
  {
  printf("%d ", a[i]);  //输出 
  }
  printf("\n");
  return 0;
}


运行结果:

2.png



冒泡法排序

冒泡排序也是我们学习算法时的一个小小的知识点,今天我们在这里为大家讲解一下:


冒泡排序(Bubble Sort)是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。


为什么要叫冒泡排序:因为数组种越小的元素会经由交换慢慢"浮"到数列的顶端,就像水中的气泡一样,会慢慢的浮到水面一样。


具体实现步骤

知道了冒泡排序,那么我们就来说一下冒泡排序的具体实现步骤:


       第一步:比较相邻的元素。如果第一个比第二个大,就交换他们两个。


       第二步:对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。注意:在这步做完后,最后的元素会是最大的数,这时我们在第二次比较的时候,就不需要去考虑最后一个数了;同理可得,我们在第三次操作的时候,就不需要去考虑后两个数了。


       第三步:持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。


实现动态演示

3.gif


对数组a进行冒泡排序:


#include <stdio.h>
int main()
{
  int a[] = { 4, 2, 3, 1, 5 }; //定义一个数组,同时初始化所有成员变量
  int i = 0;
  int j = 0;
  int n = sizeof(a) / sizeof(a[0]);
  int tmp;
  for (i = 0; i < n-1; i++) //从前向后进行循环 
  {
  for (j = 0; j < n - i -1 ; j++) //内循环的目的是比较相邻的元素,把大的放到后面
  {
    if (a[j]  > a[j + 1]) //比较 
    {
    tmp = a[j];
    a[j] = a[j+1];
    a[j+1] = tmp;
    }
  }
  }
  for (i = 0; i < n; i++)
  {
  printf("%d ", a[i]);
  }
  printf("\n");
  return 0;
}


代码实例讲解

下面我们用举例子的方式来实现一下上面的代码部分:


我们的数组就是这样的:

4.png



根据代码演示,第一步我们让i=0; j=0。此时i和j下标对应的都是首元素。

5.png



接下来我们比较j和j+1;在这里j>j+1,所以我们进行交换;


6.png


然后我们进行j++操作;

7.png



然后比较j和j+1 ,这次j>j+1;所以需要交换元素 ;

8.png



之后我们继续进行 j++; 和 判断 j 和 j+1 的大小;第一轮循环完成后数组如图所示:

9.png



然后我们进行i++操作,这时i=1;并且这次j从0开始向后循环,跟上次不一样的是,这次j循环到n-i-1前截止,也就是不需要比较最后一位的大小了,因为最后一位一定是最大的。

10.png



然后接下来我们就按照第一轮循环那样一直循环.....直到结尾。


第二轮循环完成后数组如图所示:

11.png



第三轮循环完成后数组如图所示:

12.png



第四轮循环完成后数组如图所示:

13.png



最终结果:

13.png


到这里我么你都就完成了所有步骤,下面就是完整流程图,如果里面细节有不明白的,就可以看看这个:

15.png



运行结果:

16.png



二维数组


训练要求

对于二维数组的基础训练就不向一维数组一样那么多了,针对二维数组,我们的强化练习就是利用二维数组,去做一个简易版成绩管理系统,也就是根据里面的分数去计算出平均成绩和不合格人数。


输入:对于输入来说,我们可以使用初始化方式,也可以使用for循环进行键盘输入,这两种都是可以的,这里为了方便理解,就使用初始化方式进行初始化数组


我们创建出一个二维数组,二维数组的行数就代表了我们考试的人数,而二维数组的列数,就代表了我们考试的科目。然后我们从第一位同学的每科成绩开始存起。


如果计算平均成绩的话,我们要保证列不变,也就是二维数组的第二个下标不变化,遍历第一个下标去计算平均值。


判断每科不合格也是先按列不动,遍历行数,判断该科目不合格人数,之后我们改列,然后继续遍历即可。


输出:我们使用for循环正常输出即可。


代码:

#include <stdio.h>
int main()
{
  //行代表人:  第一位到第五位 
  //列代表科目:语、数、外
  float a[5][3] = { { 80, 75, 56 }, { 59, 65, 71 }, { 59, 63, 70 }, { 85, 45, 90 }, { 76, 77, 45 } } ;
  int i, j, person_low[3] = { 0 } ;
  float s = 0, lesson_aver[3] = { 0 } ; //先让三科不合格数均为0人 
  for (i = 0; i < 3; i++)
  {
  for (j = 0; j < 5; j++)
  {
    s = s + a[j][i];
    if (a[j][i] < 60)  //判断不合格人数 
    {
    person_low[i]++;
    }
  }
  lesson_aver[i] = s / 5 ;  //计算平均数 
  s = 0;
  }
  printf("各科的平均成绩:\n");
  for (i = 0; i < 3; i++)
  {
  printf("%.2f\n", lesson_aver[i]);
  }
  printf("各科不及格的人数:\n");
  for (i = 0; i < 3; i++)
  {
  printf("%d\n", person_low[i]);
  }
  return 0;
}

运行结果:

17.png



结尾


好啦!我们本期的数组强化训练也就到这里结束了,希望大家可以通过这期训练更好的掌握数组的知识,当然这些都是比较基础的部分,到C语言强化的部分时,我们还会继续接触一些数组更深入的部分!


相关文章
|
23天前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
72 6
|
26天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
52 5
|
26天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
1月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
1月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
1月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
55 4
|
1月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
116 7
|
1月前
|
C语言 Windows
C语言课设项目之2048游戏源码
C语言课设项目之2048游戏源码,可作为课程设计项目参考,代码有详细的注释,另外编译可运行文件也已经打包,windows电脑双击即可运行效果
34 1
|
算法 编译器 程序员
C语言学习笔记—P11(数组<2>+图解+题例+三子棋游戏<初级>)
C语言学习笔记(数组<2>+图解+题例+三子棋游戏<初级>)
136 0
C语言学习笔记—P11(数组<2>+图解+题例+三子棋游戏<初级>)
|
存储 C语言
C语言学习笔记—P10(数组<1>+图解+题例)
C语言学习笔记(数组<1>+图解+题例)
145 0