【教程】C++语言基础学习笔记(七)——Array数组

文首标志
写在前面:
如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持!


【C++语言基础学习】系列文章

第一章 《项目与程序结构》
第二章 《数据类型》
第三章 《运算符》
第四章 《流程控制》
第五章 《Vector向量》
第六章 《String字符串》
第七章 《Array数组》
第八章 《函数》
第九章 《指针》
第十章 《结构体》



C++支持数组数据结构,其可以储存一个固定大小的相同类型元素的顺序集合。数组被用来储存一系列数据,但它往往被认为是一系列相同类型的变量。
数组的声明并不是声明一个个单独的变量,比如number0number1、……、number99等,而是声明一个数组变量,比如numbers,然后使用numbers[0]numbers[1]、……、numbers[99]等来代表一个个单独的变量。数组中的特定元素可以通过索引访问。
所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最好的地址对应最后一个元素。

一、一维数组

(一)一维数组定义方式

在C++中要声明一个数组,一般有三种方式。

数据类型 数组名[ 数组长度 ];// 第一种定义方式
数据类型 数组名[ 数组长度 ] = {
   1,2, ... };// 第二种定义方式
数据类型 数组名[] = {
   1,2, ... };// 第三种定义方式

以下是简单的示例。

// 第一种
int arr1[3];
arr1[0] = 10;
arr1[1] = 12;
arr1[2] = 17;
// 第二种
int arr2[3] = {
    10,12,17 };
// 第三种
int arr3[] = {
    10,12,17 };

第一种方式定义了一个数组arr1具有三个元素,然后逐一赋值。值得注意的是数组元素下标的引用是从0开始的。
第二种方式定义数组arr2也具有三个元素,但此方式将三个元素的值直接通过{}分别赋予。而当给元素赋值不完全时(如四个元素赋三个值),按顺序剩下的没有赋值的元素初始化值默认为0,即没有赋值完的元素用0填充。
第三种方式定义的数组arr3不需要定义数组长度,直接初始化各个元素的具体值即可。但也需要注意的是不能不初始化任何元素的值,会导致编译器检测不出这个数组的长度,以至于报错。

(二)一维数组数组名

一维数组的数组名是指数组在内存中存储的起始地址。在C语言中,声明一个一维数组时,可以将一个标识符用作数组名。例如,如果声明一个名为arr的一维整型数组,那么arr就是该数组的数组名。
总结来说,一维数组名称的用途有两个。

  1. 可以统计整个数组在内存中的长度
  2. 可以获取数组在内存中的首地址

统计占用内存的长度也是使用sizeof()来查看。

int arr[3] = {
    1,3,5 };
cout << "整个数组占用内存空间为:" << sizeof(arr) << endl;
cout << "每个元素占用内存空间为:" << sizeof(arr[0]) << endl;
cout << "数组中的元素个数为:" << sizeof(arr) / sizeof(arr[0]) << endl;

返回结果如下。

整个数组占用内存空间为:12
每个元素占用内存空间为:4
数组中的元素个数为:3

而获取数组首地址直接输出数组即可。

int arr[3] = {
    1,3,5 };
cout << "数组首地址(十六进制)为:" << arr << endl;// 十六进制
cout << "数组首地址(十进制)为:" << (int)arr << endl;// 十进制
cout << "数组中第一个元素地址为:" << &arr[0] << endl;

返回结果如下。

数组首地址(十六进制)为:00000018F958FB28
数组首地址(十进制)为:-111609048
数组中第一个元素地址为:00000018F958FB28

承接上一个示例,如果希望得到十六进制的首地址返回结果,直接输出数组即可;而如果希望得到十进制结果,则需要将数组转换为整型;若希望得知数组内某个元素的首地址,则需要使用取值运算符&来输出。
值得注意的是数组名是常量,不可以进行赋值操作。

(三)冒泡排序算法

冒泡排序是一种简单的排序算法,它通过依次比较相邻的元素并交换它们的位置来将一个数组按照升序或降序排列。冒泡排序的基本思想是,每一轮扫描将相邻的两个元素比较并交换位置,使得最大(或最小)的元素像气泡一样逐渐浮到数组的末尾。
简单来讲就是对数组内的元素实现了从小到大(从大到小)顺序的排列。由于结构简单,使得冒泡排序成为最常用的排序算法。
其规则如下。

  1. 从第一个元素开始,依次比较相邻的两个元素。
  2. 如果前一个元素大于(或小于)后一个元素,则交换它们的位置。
  3. 继续向后比较并交换,直到最后一个元素,这样一轮比较下来,最大(或最小)的元素就会被交换到最后。
  4. 重复执行步骤 1~3,每一轮比较都会确定一个最大(或最小)的元素的位置。
  5. 当没有发生元素交换时,排序结束。

下面是利用冒泡排序算法实现升序序列的示例。

int arr[9] = {
    4,2,8,0,5,7,1,3,9 };
cout << "排序前:" << endl;
for (int i = 0; i < 9; i++)
{
   
	cout << arr[i] << " ";
}
cout << endl;

首先,定义一个乱序的数组,用循环遍历输出一下此时数组内的排序。
返回结果如下。

排序前:
4 2 8 0 5 7 1 3 9

此时回想冒泡排序算法的原理,可以得知对9个数的排列,从需要比较的第一个数字到最后一个数字其实只有8轮(第8个数字和第9个数字比较即为最后一轮),所以排序总轮数=元素个数-1;而观察可以得知,每轮对比次数=元素个数-排序轮数-1,以此规律设计冒泡排序算法。
全部代码如下。

#include "test.h"
#include <iostream>

using namespace std;

void test::Test()
{
   
	int arr[9] = {
    4,2,8,0,5,7,1,3,9 };
	cout << "排序前:" << endl;
	for (int i = 0; i < 9; i++)
	{
   
		cout << arr[i] << " ";
	}
	cout << endl;
	// 冒泡排序
	// 总共排序轮数=元素个数-1
	for (int i = 0; i < 9 - 1; i++)
	{
   
		// 内层循环对比=每轮对比次数=元素个数-排序轮数-1
		for (int j = 0; j < 9 - i - 1; j++)
		{
   
			// 如果第一个数字比第二个数字大,则交换两个数字
			if (arr[j] > arr[j + 1])
			{
   
				// 创建临时变量承载第一个位置上较大的数字
				int temp = arr[j];
				// 令第二个位置上较小的数字转移到第一个位置上
				arr[j] = arr[j + 1];
				// 令第二个位置取回原本第一个位置上那个较大的数字
				arr[j + 1] = temp;
			}
		}
	}
	cout << "排序后:" << endl;
	for (int i = 0; i < 9; i++)
	{
   
		cout << arr[i] << " ";
	}
	cout << endl;
}

返回结果如下。

排序前:
4 2 8 0 5 7 1 3 9
排序后:
0 1 2 3 4 5 7 8 9

二、二维数组

C++支持多维数组。在 C++语言中,可以使用多维数组来存储具有多个维度的元素集合。多维数组实际上是数组的数组,每个维度都可以有自己的大小。多维数组声明的一般形式如下。

type name[size1][size2]...[sizeN];

这里主要以二维数组作为示例进行介绍。

(一)二维数组定义方式

在C++中要声明一个二维数组,一般有四种方式。

数据类型 数组名[ 行数 ][ 列数 ];// 第一种定义方式
数据类型 数组名[ 行数 ][ 列数 ] = {
    {
    数据1,数据2 },{
    数据3,数据4 } };// 第二种定义方式
数据类型 数组名[ 行数 ][ 列数 ] = {
    数据1,数据2,数据3,数据4 };// 第三种定义方式
数据类型 数组名[][ 列数 ] = {
    数据1,数据2,数据3,数据4 };// 第四种定义方式

对于第一种定义方式,test.cpp示例代码如下。

#include "test.h"
#include <iostream>

using namespace std;

void test::Test()
{
   
	// 第一种定义方式
	int arr1[2][3];
	arr1[0][0] = 1;
	arr1[0][1] = 2;
	arr1[0][2] = 3;
	arr1[1][0] = 4;
	arr1[1][1] = 5;
	arr1[1][2] = 6;
	// 外层循环打印行数,内层循环打印列数
	for (int i = 0; i < 2; i++)
	{
   
		for (int j = 0; j < 3; j++)
		{
   
			cout << arr1[i][j] << " ";
		}
		cout << endl;
	}
}

按第一种方式,定义一个2行3列的arr1二维数组,并逐个赋值,结果可以用for循环来遍历数组内容。返回结果如下。

1 2 3
4 5 6

对于第二、三、四种定义方法,承接上一个示例,test.cpp代码如下。

// 第二种定义方式
int arr2[2][3] =
{
   
	{
    1,2,3 },
	{
    4,5,6 }
};
// 第三种定义方式
int arr3[2][3] = {
    1,2,3,4,5,6 };
// 第四种定义方式
int arr4[][3] = {
    1,2,3,4,5,6 };

对于第二种定义方式,行和列的元素赋值明显,通常是最常用也是可读性最强的一种定义方式;而第三种则是在定义了行数和列数后,编译器仍能正确分类每个元素的行数和列数,从而达到预期赋值效果;第四种的原理同第三种定义方式,面对一串元素,在只有两个维度的条件下,即便仅定义了列数,编译器也能从总元素数中得出行数,从而分配赋值。需要注意的是,虽然在定义中可以省略行数,但列数却不可以省略。
代码返回结果和上一个示例相同,故不再展示。

(二)二维数组数组名

与一维数组同理,二维数组数组名也可以查看占用内存空间大小和首地址。

int arr[2][3] =
{
   
	{
    1,2,3 },
	{
    4,5,6 }
};
cout << "二维数组占用内存空间为:" << sizeof(arr) << endl;
cout << "二维数组第一行占用内存空间为:" << sizeof(arr[0]) << endl;
cout << "二维数组第一个元素占用内存空间为:" << sizeof(arr[0][0]) << endl;
cout << "二维数组中的行数为:" << sizeof(arr) / sizeof(arr[0]) << endl;
cout << "二维数组中的列数为:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;
cout << "二维数组首地址(十进制)为:" << (int)arr << endl;
cout << "二维数组第一行首地址为:" << (int)arr[0] << endl;
cout << "二维数组第二行首地址为:" << (int)arr[1] << endl;
cout << "二维数组第一个元素首地址为:" << (int)&arr[0][0] << endl;
cout << "二维数组第五个元素首地址为:" << (int)&arr[1][2] << endl;

返回结果如下。

二维数组占用内存空间为:24
二维数组第一行占用内存空间为:12
二维数组第一个元素占用内存空间为:4
二维数组中的行数为:2
二维数组中的列数为:3
二维数组首地址(十进制)为:1781529192
二维数组第一行首地址为:1781529192
二维数组第二行首地址为:1781529204
二维数组第一个元素首地址为:1781529192
二维数组第五个元素首地址为:1781529212

从返回结果来看,二维数组本身、其某一行和某个具体元素之间占用的空间都是成比例的,也就是说每个元素的占用组成了二维数组行列的占用和二维数组本身的占用。对于首地址,值得注意的是二维数组本身的首地址、第一行的首地址、第一个元素的首地址是相同的;而对于第一行和第二行的首地址相差正好是第一行的占用数。


我是EC,一个永远在学习中的探索者,关注我,让我们一起进步!

文末标志

相关推荐

  1. C#基础——数组Array数组API

    2024-02-14 16:36:01       40 阅读
  2. C++学习笔记(十

    2024-02-14 16:36:01       31 阅读
  3. C++ -- Array 学习

    2024-02-14 16:36:01       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-14 16:36:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-14 16:36:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-14 16:36:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-14 16:36:01       20 阅读

热门阅读

  1. 深入理解C#中的事件驱动编程

    2024-02-14 16:36:01       28 阅读
  2. 利用英伟达(NVIDIA)RAPIDS实现GPU加速数据科学

    2024-02-14 16:36:01       34 阅读
  3. gstreamer 常用的图片格式转换命令

    2024-02-14 16:36:01       30 阅读
  4. 15.1 OpenGL可编程片段处理:片段着色器变量

    2024-02-14 16:36:01       33 阅读
  5. 2024/2/13 图的基础知识 3(拓扑排序)

    2024-02-14 16:36:01       31 阅读
  6. AcWing 1233. 全球变暖(bfs块问题)

    2024-02-14 16:36:01       29 阅读