数组

作者: 老韩 分类: 信奥赛,算法 发布时间: 2024-05-17 00:37

在C++中,数组是一种将相同类型元素存储在一起的数据结构。当然,在其他语言,也基本都是如此。

数组有一些特点(不是优点):

  • 固定大小:一旦创建,数组的大小就固定了,不能动态改变。
  • 元素类型一致性:数组中的所有元素必须具有相同的类型。
  • 通过索引访问:可以通过整数索引来访问数组中的特定元素,索引通常从 0 开始([通常]只是这么一说,就是从0开始的)。
  • 连续存储:元素在内存中是连续存储的,这使得可以快速地顺序访问元素 (可以理解为学生排了一个队伍)。
  • 声明和初始化:可以在声明时进行初始化,例如 int arr[5] = {1, 2, 3, 4, 5}。(也可以声明的时候不初始化)
  • 多维数组:C++也支持多维数组,如二维数组等。

数组在 C++中是一种基础且常用的数据结构,广泛应用于各种程序中,用于批量处理数据(这个只是最常用的场景)等场景。

在C++中,数组到底可以用来干什么呢?

我们可以在数组中存储如一组学生的成绩、一组学生的姓名等信息;

还可以基于数组去模拟后面要学习的堆和栈的一些基本操作;

另外,在前面的排序算法中我们操作的都是数组,很多算法的学习都是基于数组来的。

数组还可以用来模拟大数,可以干很多事情的。记住数组的特点,到用的时候你就知道要用它。

数组在内容中的存储方式就像下图这样,是紧挨着的(顺序存储、如果不挨着就丢了)。

如:在代码中使用代码定义了

int a[10] = {0,0,0,0,0,0,0,0,0,0};

计算机会给数组a[10]分配了一块连续的内存空间,方便起见,地址区间记为:1000~1039。其中,内存块的首地址为base_address = 1000。

图中,第一行是访问数组时候用的下标,从0开始,明确标记每一位的位置,第二行是数组每位所占用的内存地址区间(为什么是区间,下面有讲)。

计算机会为每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。当计算即需要随机访问数组中的某个元素的时候,它会首先通过下面的寻址公式,计算该元素存存储的内存地址:

a[i]_address = base_address + i * data_type_size

其中data_type_size表示数组中每个元素的大小。例如,数组中存储的int类型的数据,所以,data_type_size就是4字节。

正式数组在内存中如此存储。所以,随机访问数组的某一个值很方便(因为可以直接计算出它的内存地址)。但是如果要在数组中插入数据就很麻烦,所以,一般我们很少在数组中进行插入、移出这种操作。

下面这段代码可以展示了如何在数组​中插入一个数据:

#include <iostream>
using namespace std;

// 在数组指定位置插入数据的函数
void insertIntoArray(int arr[], int size, int value, int position) {
	// 这个循环将要插入数据之后的值依次后移了一位
	for (int i = size; i > position; i--) {
		arr[i] = arr[i - 1];
	}
	arr[position] = value;
}

int main() {
	int arr[10] = {10, 20, 30, 40, 50};
	int newSize = 6; // 插入数据后数组中的有效数据个数
	int valueToInsert = 25; // 要插入的数据
	int positionToInsert = 2; // 要插入的位置下标

	insertIntoArray(arr, newSize - 1, valueToInsert, positionToInsert);

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

	return 0;
}

 

数组的所有操作都不能改变它的大小。

本文不涉及多维数组。刚开始,先理解并用好一维数组,多维数组在​用到的时候再聊。

因为在使用数组的时候我们会用到指针,所以我们也提前对指针做了简单的介绍:指针和引用

今天这篇主要是介绍数组的基础用法。

声明数组

type arrayName [ arraySize ];

type是类型,arrayName是数组名字,arraySize是数组大小。

在这三个部分中,数组名字没啥好说的。重点在于类型和数组大小。

回顾一下之前讲过的数组特点:

固定大小:一旦创建,数组的大小就固定了,不能动态改变。

元素类型一致性:数组中的所有元素必须具有相同的类型。

javascript:void(function(){ window.parent.parent.window.__templateCardIframeWrite(document, ‘1716306290931’, ‘insert_blockquote_source_iframe_ready_0’, true);}())

一个数组虽然存了一些列的元素,但是这些元素的类型是固定且相同的。所以这里的类型虽然修饰的是数组,但是它代表的是数组的每个元素的类型。

看下下面这段代码:

#include <iostream>
using namespace std;
int main() {
int age[10]; // 声明存储10个int数据的数组
double salary[10]; // 声明存储10个double数据的数组
int* p[10]; // 声明存储10个int指针数据的数组
for(int i=0;i<10;i++){
cout<< age[i] << "\t";
  }
cout<<endl;
for(int i=0;i<10;i++){
cout<< salary[i] << "\t";
  }
cout<<endl;
for(int i=0;i<10;i++){
cout<< p[i] << "\t";
  }
cout<<endl;
return 0;
}

 

编译运行没有报错,但是结果有点奇怪:

为什么打印的值会看起来​乱七八糟?是因为我们没有初始化!每个变量都应该尽量​及时初始化,避免出现不可预计的错误。

上面的红字是一个忠告。继续回头来看数组​。

初始化数组

那如何初始化​数组呢?​再看下面这段代码:

#include <iostream>
using namespace std;

int main() {
int age[10] = {10,20}; // 声明存储10个int数据的数组,指定age[0]=10,age[1]=20
double salary[10] = {10.1}; // 声明存储10个double数据的数组,指定salary[0]=10.1
int* p[10] = {0}; // 声明存储10个int指针数据的数组,声明所有元素的值为0

for(int i=0;i<10;i++){
cout<< age[i] << "\t";
}
cout<<endl;

for(int i=0;i<10;i++){
cout<< salary[i] << "\t";
}
cout<<endl;

for(int i=0;i<10;i++){
cout<< p[i] << "\t";
}
cout<<endl;

return 0;
}

 

运行结果:

结合代码的注释和运行结果可以​对初始化有初步的认识。

访问数组元素

前面代码中的age[i], salary[i], p[i]就是在读取元素​值了。

获取数组大小

下面这段代码在之前讲排序的时候有多次用到。

int arr[] = {64, 34, 25, 12, 22, 11, 90};  // 要排序的一维数组
int n = sizeof(arr) / sizeof(arr[0]);  // 获取数组的长度,sizeof用来获取当前对象在内存中占用的大小

 

今天的使用数组就聊到这里了。截止到这里,排序算法里面对数组的基本使用都已经​讲到了。

后面到函数部分的时候,会再次对​数组做进一步的说明。

公众号中的文章是按阶段分开的,博客里面是不断完善的。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据