14.二维数组

14.数组-二维数组


14.1 知识点

基本概念

二维数组是使用两个下标(索引)来确定元素的数组。两个下标可以理解为行标和列标。例如,矩阵:

1  2  3
4  5  6

可以用二维数组 变量名[2][3] 表示,表示两行三列的数据集合。

二维数组的声明

1. 声明一个未初始化的二维数组

int arr[3][4];

这段代码声明了一个3行4列的二维数组,相当于为其分配了3*4=12个内存位置来存储 int 类型的值,但这些值还没有初始化,因此它们是未确定的。

2. 声明并初始化二维数组

int arr2[3][4] = { {1,2,3,4},
                   {5,6,7,8},
                   {9,10,11,12} };

这段代码声明了一个3行4列的二维数组,并在声明时初始化了每个元素的值。

3. 按“房间”初始化二维数组

int arr3[3][4] = { 1,2,3,4,
                   5,6,7,8,
                   9,10,11,12 };

这段代码是另一种初始化方式,将数组按元素顺序进行初始化,而不按行初始化。

二维数组的使用

int array[3][4] = { 1,2,3,4,
                    5,6,7,8,
                    9,10,11,12 };

1. 获取数组的行数和列数

利用 sizeof 操作符来计算行数和列数:

// 获取行数
int rows = sizeof(array) / sizeof(array[0]);
cout << rows << endl; // 输出 3

// 获取列数
int cols = sizeof(array[0]) / sizeof(int);
cout << cols << endl; // 输出 4

2. 获取数组中的元素

可以通过索引访问数组中的元素:

cout << array[0][0] << endl; // 输出 1
cout << array[0][1] << endl; // 输出 2
cout << array[2][2] << endl; // 输出 11

3. 初始化所有坑位

如果只初始化了一个值,其他元素会被自动初始化为0:

int array2[3][3] = { 0 };
cout << array2[0][0] << endl; // 输出 0
cout << array2[2][2] << endl; // 输出 0

4. 修改数组中的元素

array2[0][0] = 99;
cout << array2[0][0] << endl; // 输出 99

5. 遍历二维数组

使用嵌套的 for 循环遍历二维数组:

for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        cout << array[i][j] << endl;
    }
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12

6. 增加数组的元素

数组初始化后不能直接添加新的元素,但可以通过搬家操作将数组复制到更大的二维数组中:

int array3[4][5];
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        array3[i][j] = array[i][j];
    }
}

for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        cout << array3[i][j] << endl;
    }
}

7. 删除数组的元素

删除数组元素时,需要使用搬家方法,将数据搬移到更小的数组容器中,避免越界。

8. 查找数组中的元素

通过双层 for 循环查找某个元素是否存在:

int target = 7;
bool found = false;
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        if (array[i][j] == target) {
            cout << "元素 " << target << " 在第 " << i << " 行,第 " << j << " 列" << endl;
            found = true;
            break;
        }
    }
    if (found) break;
}

输出:

元素 7 在第 1 行,第 2 列

在函数中传递二维数组

在函数中传递二维数组时,必须告知编译器该数组的列数。固定写法为:

返回值 函数名( 数组类型 数组名[][列数], int 行数 );

例如:

void test(int array[][4], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 4; j++) {
            cout << array[i][j] << endl;
        }
    }
}

test(array, rows);

输出:

1
2
3
4
5
6
7
8
9
10
11
12

14.2 知识点代码

Lesson14_数组_二维数组.cpp

#include <iostream>
using namespace std;

void test(int array[][4], int rows);

int main()
{
    std::cout << "二维数组\n";

    #pragma region 知识点一 基本概念

    //二维数组 是使用两个下标(索引)来确定元素的数组
    //两个下标可以理解成 行标  和 列标
    //比如矩阵
    // 1 2 3
    // 4 5 6 
    // 可以用二维数组 变量名[2][3] 表示 
    // 好比 两行 三列的数据集合

    #pragma endregion

    #pragma region 知识点二 二维数组的声明

    // 1.变量类型 数组名[行][列];
    //   声明一个指定行列容量的二维数组,但是每个房间的值并不确定
    //   变量类型 可以是我们学过的 或者 没学过的所有变量类型
    int arr[3][4]; //相当于就是分配了3*4=12个内存小房间用于存储int值 目前没有初始化
    //因此其中每个房间中的值 是不确定的


// 2.变量类型 数组名[行][列] = {{值,值,值.....}, {值,值,值.....}, {值,值,值.....} ....};
//   声明一个指定行列容量的二维数组,每个房间的值在声明时进行初始化
    int arr2[3][4] = { {1,2,3,4},
                       {5,6,7,8},
                       {9,10,11,12} };


    // 3.变量类型 数组名[行][列] = {值,值,值,.....};
    //    上面是按行去初始化,我们也可以按“房间”初始化
    int arr3[3][4] = { 1,2,3,4,
                       5,6,7,8,
                       9,10,11,12 };

    #pragma endregion

    #pragma region 知识点三 二维数组的使用

    int array[3][4] = { 1,2,3,4,
                        5,6,7,8,
                        9,10,11,12 };

    //1.数组的长度
    //  利用sizeof进行计算
    //获取行数
    //         4 * 12 = 48          /      4 * 4 = 16            =   3
    int rows = sizeof(array) / sizeof(array[0]);
    cout << rows << endl; // 3(计算得到二维数组 array 的行数为 3)
    //获取列数
    //         4 * 4 = 16       /     4         =   4
    int cols = sizeof(array[0]) / sizeof(int);
    cout << cols << endl; // 4(计算得到二维数组 array 的列数为 4)

    //2.获取数组中的元素
    //  注意:第一个元素的索引是0 最后一个元素的索引 肯定是长度 - 1
    cout << array[0][0] << endl; // 1(输出二维数组 array 第一行第一列的元素,值为 1)
    cout << array[0][1] << endl; // 2(输出二维数组 array 第一行第二列的元素,值为 2)
    cout << array[2][2] << endl; // 11(输出二维数组 array 第三行第三列的元素,值为 11)

    //3.初始化所有坑位
    //  至少初始化一个值,后面的坑位会用0进行初始化
    int array2[3][3] = { 0 };
    cout << array2[0][0] << endl; // 0(输出二维数组 array2 第一行第一列的元素,值为 0)
    cout << array2[2][2] << endl; // 0(输出二维数组 array2 第三行第三列的元素,值为 0)

    //4.修改数组中的元素
    array2[0][0] = 99;
    cout << array2[0][0] << endl; // 99(输出修改后的二维数组 array2 第一行第一列的元素,值为 99)

    cout << "**********************" << endl;
    //5.遍历二维数组
    // 套路:用两个for循环进行嵌套
    //行
    for (int i = 0; i < rows; i++)
    {
        //列
        for (int j = 0; j < cols; j++)
        {
            //行 i  0 1 2
            //列 j  0 1 2 3
            // i j
            // 0 0 = 1
            // 0 1 = 2
            // 0 2 = 3
            // 0 3 = 4
            // 1 0 = 5
            // 1 1 = 5
            // 1 3 = 5
            //.......
            cout << array[i][j] << endl;
            // 输出:
            // 1(第一次循环,i = 0, j = 0)
            // 2(第一次循环,i = 0, j = 1)
            // 3(第一次循环,i = 0, j = 2)
            // 4(第一次循环,i = 0, j = 3)
            // 5(第二次循环,i = 1, j = 0)
            // 6(第二次循环,i = 1, j = 1)
            // 7(第二次循环,i = 1, j = 2)
            // 8(第二次循环,i = 1, j = 3)
            // 9(第三次循环,i = 2, j = 0)
            // 10(第三次循环,i = 2, j = 1)
            // 11(第三次循环,i = 2, j = 2)
            // 12(第三次循环,i = 2, j = 3)
        }
    }

    //6.增加数组的元素
    //  数组初始化以后 是不能够 直接添加新的元素的
    //搬家
    // 在搬家过程中 要以这个容量更小的二维数组容器为主 否则会越界
    int array3[4][5];
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            array3[i][j] = array[i][j];
        }
    }

    // 为了观察 array3 中的元素,我们遍历它
    cout << "**********************" << endl;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            cout << array3[i][j] << endl;
            // 输出:
            // 1(第一次循环,i = 0, j = 0)
            // 2(第一次循环,i = 0, j = 1)
            // 3(第一次循环,i = 0, j = 2)
            // 4(第一次循环,i = 0, j = 3)
            // 5(第二次循环,i = 1, j = 0)
            // 6(第二次循环,i = 1, j = 1)
            // 7(第二次循环,i = 1, j = 2)
            // 8(第二次循环,i = 1, j = 3)
            // 9(第三次循环,i = 2, j = 0)
            // 10(第三次循环,i = 2, j = 1)
            // 11(第三次循环,i = 2, j = 2)
            // 12(第三次循环,i = 2, j = 3)
        }
    }

    //7.删除数组的元素
    //  原理相同 需要搬家
    // 在搬家过程中 要以这个容量更小的二维数组容器为主 否则会越界

    //8.查找数组中的元素
    // 如果要在数组中查找一个元素是否等于某个值
    int target = 7;
    bool found = false;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            if (array[i][j] == target)
            {
                cout << "元素 " << target << " 在第 " << i << " 行,第 " << j << " 列" << endl;
                // 输出:元素 7 在第 1 行,第 2 列
                found = true;
                break;
            }
        }
        if (found)
            break;
    }

    #pragma endregion


    cout << "*************" << endl;

    #pragma region 知识点四 在函数中传递二维数组

    //知识回顾
    //在函数中传递一维数组时
    //传入的本质上是一个指向首地址的指针
    //因此在内部我们无法准确获取数组的容量信息
    //需要从外部传入容量信息
    // 固定写法:
    // 返回值 函数名( 数组类型 数组名[], int 容量 )

    //二维数组
    //在函数中传递二维数组是一种特殊的写法
    //你必须告诉编译器二维数组有多少列
    // 固定写法:
    // 返回值 函数名( 数组类型 数组名[][列数], int 行数 )

    test(array, rows);
    //1
    //2
    //3
    //4
    //5
    //6
    //7
    //8
    //9
    //10
    //11
    //12

    #pragma endregion

}

//函数中传递二维数组的固定写法
//返回值 函数名( 数组类型 数组名[][列数], int 行数 )
void test(int array[][4], int rows)
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            cout << array[i][j] << endl;
        }
    }
}

#pragma region 总结

//1.概念:同一变量类型的 行列数据集合
//2.一定要掌握的内容:声明、遍历、增删查改
//3.所有的变量类型都可以声明为二维数组
//4.我们目前学习的声明方式 静态数组,以后学习堆中分配的动态数组
//5.二维数组在函数中应该如何传递 返回值 函数名( 数组类型 数组名[][列数], int 行数 )
//6.游戏中一般会用二维数组 来存储 矩阵,在控制台小游戏中我们可以用二维数组来表示 地图的格子

#pragma endregion

14.3 练习题

将1到10000赋值给一个二维数组(100行100列)

// 声明一个二维数组 array,大小为 100x100
int array[100][100];
// 计算二维数组的行数,sizeof(array) 表示整个二维数组的大小,sizeof(array[0]) 表示一行的大小,相除得到行数
int rows = sizeof(array) / sizeof(array[0]);
// 计算二维数组的列数,sizeof(array[0]) 表示一行的大小,sizeof(int) 表示一个元素的大小,相除得到列数
int cols = sizeof(array[0]) / sizeof(int);
// 初始化一个索引变量 index,初始值为 1
int index = 1;
// 外层 for 循环,遍历行
for (int i = 0; i < rows; i++)
{
    // 内层 for 循环,遍历列
    for (int j = 0; j < cols; j++)
    {
        // 将 index 的值赋给当前元素 array[i][j]
        array[i][j] = index;
        // 输出当前元素的值
        cout << index << " ";
        // 索引值加 1
        ++index;
    }
    // 输出换行符,使输出更具可读性
    cout << endl;
}

将二维数组(4行4列)的右上半部分置零(元素随机1~100)

int arr2[4][4];
for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
        // 判断是否为右上半部分
        if (i < 2 && j > 1) {
            // 将右上半部分元素置为 0
            arr2[i][j] = 0;
        }
        else {
            // 给其他元素赋值为 1 到 100 的随机数
            arr2[i][j] = getRandom(1, 100);
        }
        // 输出当前元素的值
        cout << arr2[i][j] << " ";
    }
    // 输出换行符,使输出更具可读性
    cout << endl;
}

求二维数组(3行3列)的对角线元素的和(元素随机1~10)

int arr3[3][3];
// 用来记录总和
int sum = 0;
for (int i = 0; i < sizeof(arr3) / sizeof(arr3[0]); i++) {
    for (int j = 0; j < sizeof(arr3[0]) / sizeof(int); j++) {
        // 给元素赋值为 1 到 10 的随机数
        arr3[i][j] = getRandom(1, 10);
        // 输出当前元素的值
        cout << arr3[i][j] << " ";
        // 判断是否为对角线上的元素,如果是则累加到 sum 中
        if (i == j || i + j == 2) {
            sum += arr3[i][j];
        }
    }
    // 输出换行符,使输出更具可读性
    cout << endl;
}
// 输出对角线上元素的总和
cout << "对角线上的数字总和为" << sum;

求二维数组(5行5列)中最大元素值及其行列号(元素随机1~500)

// 我们声明两个变量 用于记录最大值的行列号
int maxI = 0;
int maxJ = 0;
int arr4[5][5];
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        // 随机一个值 1~500
        arr4[i][j] = getRandom(1, 500);
        // 输出当前元素的值
        cout << arr4[i][j] << " ";
        // 不停的去比较 记录最大元素的 行和列
        if (arr4[maxI][maxJ] < arr4[i][j]) {
            maxI = i;
            maxJ = j;
        }
    }
    // 输出换行符,使输出更具可读性
    cout << endl;
}
// 输出数组中最大元素的值以及对应的行和列
cout << "数组中最大的值是" << arr4[maxI][maxJ] << "对应的行是" << maxI << "对应的列是" << maxJ;

给一个M*N的二维数组,数组元素的值为0或者1,要求转换数组,将含有1的行和列全部置1

int arr5[5][5] = {
    0,0,0,0,0,
    0,0,0,0,0,
    0,1,0,0,0,
    0,0,1,1,0,
    1,0,0,0,0
};
// 用于记录行和列是否变为 1 的标识数组 默认其中都是 false
bool hang[5] = { 0 };
bool lie[5] = { 0 };
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        // 若元素为 1,则标记相应的行和列
        if (arr5[i][j] == 1) {
            hang[i] = true;
            lie[j] = true;
        }
        // 输出当前元素的值
        cout << arr5[i][j] << " ";
    }
    // 输出换行符,使输出更具可读性
    cout << endl;
}
cout << "********************" << endl;
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        // 根据标记将元素置为 1
        if (hang[i] || lie[j]) {
            arr5[i][j] = 1;
        }
        // 输出当前元素的值
        cout << arr5[i][j] << " ";
    }
    // 输出换行符,使输出更具可读性
    cout << endl;
}

14.4 练习题代码

Lesson14_练习题.cpp

#include <iostream>
#include "CustomConsole.h"
using namespace std;
int main()
{
    std::cout << "二维数组 练习题\n";

    #pragma region 练习题一

    //将1到10000赋值给一个二维数组(100行100列)

    // 声明一个二维数组 array,大小为 100x100
    int array[100][100];
    // 计算二维数组的行数,sizeof(array) 表示整个二维数组的大小,sizeof(array[0]) 表示一行的大小,相除得到行数
    int rows = sizeof(array) / sizeof(array[0]);
    // 计算二维数组的列数,sizeof(array[0]) 表示一行的大小,sizeof(int) 表示一个元素的大小,相除得到列数
    int cols = sizeof(array[0]) / sizeof(int);
    // 初始化一个索引变量 index,初始值为 1
    int index = 1;
    // 外层 for 循环,遍历行
    for (int i = 0; i < rows; i++)
    {
        // 内层 for 循环,遍历列
        for (int j = 0; j < cols; j++)
        {
            // 将 index 的值赋给当前元素 array[i][j]
            array[i][j] = index;
            // 输出当前元素的值
            cout << index << " ";
            // 索引值加 1
            ++index;
        }
        // 输出换行符,使输出更具可读性
        cout << endl;
    }

    #pragma endregion

    #pragma region 练习题二

    //将二维数组(4行4列)的右上半部分置零(元素随机1~100)

    int arr2[4][4];
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            // 判断是否为右上半部分
            if (i < 2 && j > 1) {
                // 将右上半部分元素置为 0
                arr2[i][j] = 0;
            }
            else {
                // 给其他元素赋值为 1 到 100 的随机数
                arr2[i][j] = getRandom(1, 100);
            }
            // 输出当前元素的值
            cout << arr2[i][j] << " ";
        }
        // 输出换行符,使输出更具可读性
        cout << endl;
    }

    #pragma endregion

    #pragma region 练习题三
    //求二维数组(3行3列)的对角线元素的和(元素随机1~10)

    int arr3[3][3];
    // 用来记录总和
    int sum = 0;
    for (int i = 0; i < sizeof(arr3) / sizeof(arr3[0]); i++) {
        for (int j = 0; j < sizeof(arr3[0]) / sizeof(int); j++) {
            // 给元素赋值为 1 到 10 的随机数
            arr3[i][j] = getRandom(1, 10);
            // 输出当前元素的值
            cout << arr3[i][j] << " ";
            // 判断是否为对角线上的元素,如果是则累加到 sum 中
            if (i == j || i + j == 2) {
                sum += arr3[i][j];
            }
        }
        // 输出换行符,使输出更具可读性
        cout << endl;
    }
    // 输出对角线上元素的总和
    cout << "对角线上的数字总和为" << sum;

    #pragma endregion

    #pragma region 练习题四

    //求二维数组(5行5列)中最大元素值及其行列号(元素随机1~500)

    // 我们声明两个变量 用于记录最大值的行列号
    int maxI = 0;
    int maxJ = 0;
    int arr4[5][5];
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            // 随机一个值 1~500
            arr4[i][j] = getRandom(1, 500);
            // 输出当前元素的值
            cout << arr4[i][j] << " ";
            // 不停的去比较 记录最大元素的 行和列
            if (arr4[maxI][maxJ] < arr4[i][j]) {
                maxI = i;
                maxJ = j;
            }
        }
        // 输出换行符,使输出更具可读性
        cout << endl;
    }
    // 输出数组中最大元素的值以及对应的行和列
    cout << "数组中最大的值是" << arr4[maxI][maxJ] << "对应的行是" << maxI << "对应的列是" << maxJ;

    #pragma endregion

    #pragma region 练习题五

    //给一个M*N的二维数组,数组元素的值为0或者1,要求转换数组,将含有1的行和列全部置1

    int arr5[5][5] = {
        0,0,0,0,0,
        0,0,0,0,0,
        0,1,0,0,0,
        0,0,1,1,0,
        1,0,0,0,0
    };
    // 用于记录行和列是否变为 1 的标识数组 默认其中都是 false
    bool hang[5] = { 0 };
    bool lie[5] = { 0 };
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            // 若元素为 1,则标记相应的行和列
            if (arr5[i][j] == 1) {
                hang[i] = true;
                lie[j] = true;
            }
            // 输出当前元素的值
            cout << arr5[i][j] << " ";
        }
        // 输出换行符,使输出更具可读性
        cout << endl;
    }
    cout << "********************" << endl;
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            // 根据标记将元素置为 1
            if (hang[i] || lie[j]) {
                arr5[i][j] = 1;
            }
            // 输出当前元素的值
            cout << arr5[i][j] << " ";
        }
        // 输出换行符,使输出更具可读性
        cout << endl;
    }

    #pragma endregion

}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏