知识点
概念
按顺序排列的一组同种类型的变量构成的集合。一个数组在内存中占一片连续的存储单元。
定义
数据类型 数组名 [整数1] [整数2] …… [整数n];
如: int a[5]
引用
数组名 [下标]
(1)数组下标(index)都是从0开始
(2)下标既可是常量,也可是整型表达式
(3)允许快速随机访问
输入与输出
一、采用循环语句结合下标变化,逐个元素进行。
(1) 键盘逐个读入数组元素值;
(2) 给每个数组元素直接赋值;
二、函数赋值
(1)memset 函数
memset 函数是给数组“按字节”进行赋值,一般用在 char 型数组中,如果是 int 类型的数组,一般赋值为 0 和 -1。使用前需要包含头文件:#include 。
(2)fill 函数
fill 函数是给数组“按元素”进行赋值,可以是整个数组,也可以是部分连续元素,可以赋任何值。使用前需要包含头文件:#include 。
例如:
#include
#include
using namespace std;
int main(){
int a[10],b[10],c[10],d[10],i;
memset(a,0,sizeof(a)); // 将a数组所有元素均赋值为0
for(i = 0; i < 9; i++) cout << a[i] << “ “ ;
cout << a[9] << endl;
memset(b,1,sizeof(b));// 将 b 数组所有元素均赋值为
//二进制数 20+28+216+224=16843009
for(i = 0; i < 9; i++) cout << b[i] << “ “ ;
cout << b[9] << endl;
memset(c,0,5);
//将 c 数组前 5 个字节都赋值为 0,所以只能确定 c[0]
//等于0,其他元素值不确定
for(i = 0; i < 9; i++) cout << c[i] << “ “ ;
cout << c[9] << endl;
fill(d,d+5,8);
//将 d 数组前 5 个元素都赋值为 8,其他元素值不确定
for(i = 0; i < 9; i++) cout << d[i] << “ “ ;
cout << d[9] << endl;
return 0;
}
插入与删除元素
插入一个元素,需要先找到插入的位置(假设下标为 x),将这个元素及其之后的所有元素依次往后移一位(注意要从后往前进行操作),再将给定的元素插入(覆盖)到位置 x。
删除某一个元素,也需要先找到删除的位置(假设下标为 x),将下标为 x+1 及其之后的所有元素依次向前移一位,覆盖原来位置上的元素。
例如:
有 n 个人(每个人有一个唯一的编号,用 1~n 之间的整数表示)在一个水龙头前排队准备接水,现在第 x 个人有特殊情况离开了队伍,求第 x 个人离开队伍后的排队情况。
【输入格式】
第一行 1 个正整数 n,表示有 n 个人,2<n≤100。5
第二行包含n个正整数,之间用一个空格隔开,表示排在队伍中的第1个到第n个人的编号。
第三行包含 1 个正整数 x,表示第 x 个人离开队伍,1≤x≤n。
【输出格式】
一行包含 n-1 个正整数,之间用一个空格隔开,表示第 x 个人离开队伍后的排队情况。
【输入样例】
7
7 2 3 4 5 6 1
3
【输出样例】
7 2 4 5 6 1
#include
using namespace std;
int main(){
int n,i,x,q[102];
scanf( “ %d ” ,&n);
for(i = 1; i <= n; i++) scanf( “ %d ” ,&q[i]);
scanf( “ %d ” ,&x);
for(i = x; i < n; i++) q[i] = q[i+1];
n–;
for(i = 1; i < n; i++) printf( “ %d “ ,q[i]);
printf( “ %d\n ” ,q[n]);
return 0;
}
数据查找
一维数组的查找操作,就是在一维数组中查找有没有某个元素,它的值等于指定的值 x。查找操作的结果可能是一个没找到、找到一个或者找到很多个。
(1)“顺序”查找
顺序查找就是按照从前往后的顺序,将数组中的元素依次与要查找的数 x 进行比较。
(2)二分查找
二分查找又称“折半”查找,其优点是比较次数少、查找速度快。但是要求数据是递增或递减排序的。
例如:
int left = 0,right = n - 1;
int find = n;//find标记找到的位置,初始化为n,表示没找到
while(left <= right){
int mid = (left + right) / 2;
if(a[mid] == x){//找到了,就标记位置,并退出循环
find = mid;
break;
}
if(x < a[mid]) right = mid - 1;//x只能在左半部分
if(a[mid] < x) left = mid + 1; //x只能在右半部分
}
if(find != n) printf("%d\n",find);
else printf(“not find\n”);
数据排序
“排序”就是按照某个关键字的大小,将若干对象从小到大或者从大到小进行重新排列。关键字是对象的某一个属性,它可以是任何基本数据类型,甚至结构体等。
(1)选择排序
main(){
int a[100000];
int i,j,max,l;
cin>>n;
for(i=0;i<n;i++) cin>> a[i];
for(j=0;j<n-1;j++)
{ l=j;
for(i=1;i<n;i++)
if(a[l]<a[i])
l=I;
if(l!=j) i=a[l],a[l]=a[j],a[j]=i;
}
return 0;
}
(2)插入排序
void insSort(int *a,int num)
{
for(i=1;i<num;i++)
{
l= i-1;temp=a[i];
while(l>=0&&a[l]>temp)
{
a[l+1]=a[l];
l–;
}
a[l+1]=temp;
}
}
(3)冒泡排序
#include
#include
using namespace std;
const int n=10;
int t,a[n+1]; //定义数组
int main()
{
for (int i=1; i<=n; ++i) cin>>a[i]; //输入十个数
for (int j=1; j<=n-1; ++j) //冒泡法排序
for (int i=1; i<=n-j; ++i) //两两相比较
if (a[i]<a[i+1]) //比较与交换
{t=a[i]; a[i]=a[i+1]; a[i+1]=t;}
for (int i=1; i<=n; ++i)
cout<<setw(5)<<a[i]; //输出排序后的十个数
cout<<endl;
return 0;
}
运行结果:
输入: 2 5 8 6 12 34 65 22 16 55
输出: 65 55 34 22 16 12 8 6 5 2
(4)sort函数
#include using namespace std;默认的sort函数是按升序排。sort(a,a+n); //两个参数分别为待排序数组的首地址和尾地址
#include
#include
using namespace std;
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10);
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
例如:
【问题描述】
给出 n 个同学的身高,请根据他们的身高升序排列并输出排序结果。
【输入格式】
第一行 1 个正整数 n,表示有 n 个同学的身高,2<n≤100。
第二行包含 n 个正整数,之间用一个空格隔开,表示 n 个同学的身高。每个同学的身高都在 150~200 厘米之间。
【输出格式】
一行 n 个正整数,之间用一个空格隔开,表示 n 个同学根据身高升序排列的结果。
【输入样例】
7
180 170 176 160 155 150 160
【输出样例】
150 155 160 160 170 176 180
选择排序
#include
using namespace std;
int main(){
int n,i,j,k,temp,h[101];
cin >> n;
for(i = 1; i <= n; i++) cin >> h[i];
for(i = 1; i <= n; i++){
k = i;
for(j = i+1; j <= n; j++)
if(h[j] < h[k]) k = j;// 在 i~n 之间的最小元素
temp = h[i];
h[i] = h[k];
h[k] = temp;// 将 i~n 之间的最小元素放到第 i 个位置
}
for(i = 1; i < n; i++) cout << h[i] << “ “ ;
cout << h[n] << endl;
return 0;
}
冒泡排序
#include
using namespace std;
int main(){
int n,i,j,temp,h[101];
cin >> n;
for(i = 1; i <= n; i++) cin >> h[i];
for(i = 1; i < n; i++)
for(j = 1; j <= n-i; j++)
if(h[j] > h[j+1]){
temp = h[j];
h[j] = h[j+1];
h[j+1] = temp;
}
for(i = 1; i < n; i++) cout << h[i] << “ “ ;
cout << h[n] << endl;
return 0;
}
插入排序
#include
using namespace std;
int main(){
int n,i,j,k,temp,h[101];
cin >> n;
for(i = 1; i <= n; i++) cin >> h[i];
for(i = 2; i <= n; i++){
temp = h[i];
k = 1;
while(h[k] <= temp && k < i) k++;
for(j = i-1; j >= k; j–) h[j+1] = h[j];
h[k] = temp;
}
for(i = 1; i < n; i++) cout << h[i] << “ “ ;
cout << h[n] << endl;
return 0;
}
二维数组
定义:
类型标识符 数组名 [ 常量表达式 1][ 常量表达式 2];
常量表达式 1 的值表示第一维大小,常量表达式 2 的值表示第二维大小,常量表达式 1 和常量表达式 2 的乘积就是二维数组的元素个数。
在二维数组定义的同时,可以进行初始化赋值。例如:
int a[2][3] = {{1,2,3},{4,5,6}};//分行初始化
也可以给数组中的部分元素初始化。例如:
int a[2][3] = {{1,2},{4}};
第一行只有2个初值, 按顺序分别赋值给a[0][0]和a[0][1],第二行的初值4赋给a[1][0],其它元素默认为0。
输入输出用循环嵌套
数字方阵
数字方阵就是一个行列数相等的二维数组,其中的每个元素都是数字。解决数字方阵问题。
(1)解析法
找出每一个方阵元素 f [i][j] 与 i、j 和数组规模n的通项公式,然后直接用两重循环给数组元素赋值,相对比较容易,一般用在初始化等场合。
(2)模拟法
把数字方阵看成一个动态的填数过程,把 n^2 个数依次填入数组中,每填好一个数,就定位好下一个数的位置 i 和 j。
字符数组
数组中的每个元素都是一个字符的数组称为“字符数组”。有时,把一维字符数组又称为“字符串”。定义字符数组的方法与定义其他类型数组的方法类似。
字符数组在计算机内部的存储最后有"/0"
用字符常量逐个初始化:char letter[5]={‘a’,‘e’,‘i’,‘o’,‘u’};
输入
用赋值语句逐个元素赋值:letter[0]=‘a’;…
用 scanf 读入整个数组:scanf ("%s",letter);
用 scanf 逐个元素读入:scanf ("%c",&letter[0]);…
用 cin 输入整个数组:cin >> letter;
用 cin 逐个元素输入:cin >> letter[0];…
用 gets 读入整个数组:gets(letter);
用 getchar 逐个读入:letter[0]=getchar();…
输出
用 cout 输出整个数组:cout >> letter;
用 cout 逐个元素输出:cout >> letter[0];…
用 printf 输出整个数组:printf ("%s",letter);
用 printf 逐个元素输出:printf ("%c",letter[0]);…
用 puts 输出整个数组:puts(letter);
用 putchar 逐个元素输出:putchar(letter[0]);…
快速读入字符串函数
int scan(){
int res = 0, flag = 0;
char ch;
if((ch = getchar()) == ‘-’) flag = 1;
else if(ch >= ‘0’ && ch <= ‘9’) res = ch - ‘0’;
while((ch = getchar()) >= ‘0’ && ch <= ‘9’)
res = res * 10 + (ch - ‘0’);
return flag ? -res : res;
}
重点难点
(1)数组大小必须是值为正的常量,不能为变量
一旦定义,不能改变大小
原因:
数组名表示数组的首地址,其值不可改变!
(2)下届越界
数组下标,从零开始,注意下标,不要越界
(3)冒泡排序,一趟排序下来,都没有任何“逆序”数对,即没有发生“交换”操作,则说明已经排好序了。此时,就可以立刻退出循环。
排序例题优化:
#include
using namespace std;
int main(){
int n,i,j,temp,h[101];
cin >> n;
for(i = 1; i <= n; i++) cin >> h[i];
for(i = 1; i < n; i++){
bool flag = true;
for(j = 1; j <= n-i; j++)
if(h[j] > h[j+1]){
temp = h[j];
h[j] = h[j+1];
h[j+1] = temp;
flag = false;
}
if(flag) break;
}
for(i = 1; i < n; i++) cout << h[i] << “ “ ;
cout << h[n] << endl;
return 0;
}
(4)刚挑选某些元素摄,可使用筛选法
筛选法
称为筛法,是由希腊著名数学家埃拉托色尼 (Eratosthenes) 提出的。相比穷举法,筛选法的效率更高。以求 1~20 之内素数为例,具体步骤如下:
(1) 将所有数(2~n)放入“筛子”中,把 1 删除;
(2) 2 在筛中,将 2 的倍数 2,4,…,20 删除(筛去);
(3) 3 在筛中,将 3 的倍数 6,9,…,18 删除(筛去);
(4) 4 不在筛中,不执行删除(筛去)操作;
……
(10) 10 不在筛中,不执行删除(筛去)操作。
例如:
【问题描述】
某商场的仓库中有 n 种商品,每件商品按 1~n 依次编号。现在商场经理突发奇想,决定将编号为素数(质数)的所有商品拿出来搞优惠酬宾活动。请编程帮助仓库管理员将编号为素数的商品选出来。
【输入格式】
一行一个正整数 n,表示有 n 种商品,2≤n≤100000。
【输出格式】
一行若干个正整数,表示若干种商品编号且每个编号均为素数,请从小到大输出,每两个数之间有一个空格。
【输入样例】
20
【输出样例】
2 3 5 7 11 13 17 19
#include
#include
using namespace std;
int main(){
int n,i,j;
bool p[100001];
for(i = 0; i <= 100000; i++) p[i] = true;
p[1] = false;
cin >> n;
cout << 2;
for(i = 2; i <= sqrt(n); i++)
if(p[i]) for(j = 2; ij <= n; j++) p[ij] = false;
for(i = 3; i <= n; i++) if(p[i]) cout << “ “ << i;
cout << endl;
return 0;
}
(5)在定义二维数组时,可以省略第一维的大小,但是第二维的大小不能省略。例如,“int a[][5];”是允许的,被省略的第一维大小根据初值的个数由系统来确定。例如:
int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
系统根据{ }中的元素个数,自动确定a数组的第一维大小为3。
个人感受
在本阶段的学习中,我认识到了解题思路的重要性。写程序时,解题思路应该对所有数据具有普遍性,这就要求我们要想到每一个可能的特例,在此基础上进行解题,否则程序就是不完整的,是失败的。
其次,在程序编写中应注意各种结构的嵌套,注意先后多用大括号梳理结构,尽量减少嵌套,简化结构
最后,我认识到对于计算机编程来说递推关系往往比较简单。
本文详细介绍了数组的概念、定义、引用方式以及数组的输入输出、初始化、插入删除元素的操作。重点讨论了如何使用 memset 和 fill 函数进行数组赋值,并通过示例展示了数组排序、查找、数据结构的应用,包括冒泡排序、选择排序、插入排序和二分查找。此外,还探讨了数组在实际问题中的应用,如队伍排队调整和素数筛选。最后,作者分享了在学习数组过程中关于解题思路和程序结构的心得体会。

1480

被折叠的 条评论
为什么被折叠?



