1. 主页
  2. 文档
  3. Level2题解(1-10)
  4. 第1课 一维数组

第1课 一维数组

输入两个学生的成绩, 我们可以定义两个变量来存储, 可是如果输入全班的学生的成绩, 怎么存放呢? 全校学生的成绩呢? 这时, 我们需要用到数组.

数组: 是相同数据类型组成的集合。

一维数组

声明: 数据类型 数组名[大小]

声明和定义:数据类型 数组名[大小] = {数组元素}

例子:

int a[6] = {10, 20, 30, 40,};
数组下标0123456
数组元素1020304000随机值
取数组值a[0]a[1]a[2]a[3]a[4]a[5]a[x]越界

测试代码:

#include <iostream>
using namespace std;

int main()
{
int a[6] = {10, 20, 30, 40};

for(int i = 0; i <= 10; i++) {
cout << a[i] << " ";
}

return 0;
}

最重要特性: 连续! 连续! 连续! 的一块内存

这样对吗?

int n;
cin >> n;
int a[n]; //对吗?
const int N = 10000;
int a[N];

c++不支持变量定义数组长度, 虽然c支持

选择题:

c++ 中数组a[10], 下面表述正确的是()

A: a代表了是a[1]的地址
B: a代表了整个数组的元素
C: a代表了数组的首地址
D: a的值可以改变

一维数组的初始化

  • 依次赋值
    int a[3] = {1,2,3};
  • 部分赋值
    int a[3] = {1,};
  • 单个赋值
    int a[3]; a[0] = 1; a[1] = 2;

这样对吗? 为什么

int a[10] = {10, 1, };
int b[10];
b = a; // 对吗? c++ 为什么不支持呢?

数组大小

sizeof(a) // 返回a占用内存的字节数. 注意不是数组元素的个数.

数组的越界

  • 数组下标不能是负数
  • 下标应该在数组长度之内
int a[N]; // 数组元素的下标值为 0 - (N-1)

for(int i = 0; i < n; i++) {
if(a[i] > a[i-1]) { //不小心就越界了, 还有可能是a[n+1]
;
}
}

每次写完数组的循环, 都要带入数组下标的边界值确认是否越界

内存操作函数

  • memcpy
void *memcpy(void *destin, void *source, unsigned n);

从存储区 source 复制 n 个字节到存储区 destin

int a[10] = {10, 1, };
int b[10];
memcpy(b, a, sizeof(b));
  • memset
void *memset(void *buffer, int ch, size_t n);

buffer 是指针或者数组,ch是要初始化的变为的字符,count是buffer的长度

// 清零
int a[100];
memset(a, 0, sizeof(a));

//极大值
memset(a, 0x7f, sizeof(a));

// -1
memset(a, -1, sizeof(a));

数组类型

int a[100];
char str[100];
long long lla[100];

一维数组的应用模板

  • 输入, 输出和遍历
int  a[100000];
int n;
scanf("%d", &n);

for(int i = 0; i < n; i++) {
scanf("%d", &a[i]); //依次读入每个元素
}

for(int i = 0; i < n; i++) {
printf("a[%d]=%d", i, a[i]); //打印数组,用于调试
}
  • 删除

删除第i个, 后面的元素要前移

  • 插入

i下标插入 x, 原来i和i之后的元素要后移动.

例题1

  • 题目描述
    一个学校有100个教室, 每个教室有一盏灯, 开关控制, 拉一下,是开, 再拉一下是关. 教室编号从 1 – 100. 开始时, 所有的灯都是关的. 第一个学生把所有的灯的开关都拉一下, 第二个学生把所有编号是2的倍数的教室的灯开关都拉1下. 第三个学生把所有编号是3的倍数的灯都拉1下 … 以后每个学生都是如此.当第100个学生拉完开关后, 哪些灯是亮的呢?
  • 分析
    灯开关状态怎么表示?
    教室怎么表示?
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
int a[108];
memset(a, 0, sizeof(a));

for(int i = 1; i <= 100; i++) {
for(int j = 1; j*i <= 100; j++) {
if (a[i*j] == 1)
a[i*j] = 0;
else
a[i*j] = 1;
}
}

for(int i = 1; i <= 100; i++) {
if(a[i] == 1)
cout << i << " ";
}

return 0;
}

例题 2

P5728 【深基5.例5】旗鼓相当的对手

  • 题目描述
    现有 N(N≤1000) 名同学参加了期末考试,并且获得了每名同学的信息:语文、数学、英语成绩(均为不超过 150 的自然数)。如果某对学生 <i,j> 的每一科成绩的分差都不大于 5,且总分分差不大于 10,那么这对学生就是“旗鼓相当的对手”。现在想知道这些同学中,有几对“旗鼓相当的对手”?同样一个人可能会和其他好几名同学结对。
  • 输入格式
    第一行一个正整数 N。

接下来 N 行,每行三个整数,其中第 i 行表示第 i 名同学的语文、数学、英语成绩。最先读入的同学编号为 1。

  • 输出格式
    输出一个个整数,表示“旗鼓相当的对手”的对数。
  • 输入输出样例3
    90 90 90
    85 95 90
    80 100 91
    • 输出
      2
    • 输入
  • 分析
    数据怎么存储呢?
    怎么进行两两比较呢?
  • 参考代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

const int MAXN = 1002;
int n, a[MAXN], b[MAXN], c[MAXN], sum[MAXN];
int ans;

int main()
{
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i] >> b[i] >> c[i];
sum[i] = a[i] + b[i] + c[i];
}

for(int i = 1; i <= n; i++) {
for(int j = i+1; j <= n; j++) {
if(abs(a[i] - a[j]) <= 5 &&
abs(b[i] - b[j]) <= 5 &&
abs(c[i] - c[j]) <= 5 &&
abs(sum[i] - sum[j]) <= 10)
ans++;
}
}

cout << ans;

return 0;
}

作业

作业 1:

  • P1428 小鱼比可爱
  • P1047 校门外的树
  • P1554 梦中的统计
  • P2141 珠心算测验

作业 2:

  • P1427 小鱼的数字游戏
  • P5728 【深基5.例5】旗鼓相当的对手
  • P2550 [AHOI2001]彩票摇奖
  • P1161 开灯

文章