vector 二维数组_干货 | 名企高频考点之C++ STL 二维vector的写法,先行再列和先列再行遍历...

bdef7eaa7c73e8824b3dd41c3fb5eaab.png

点击蓝字关注我哦

90aa5b5fa2bcb9ecd78edb96cafa952c.png 以下是本期干货视频 视频后还附有文字版本哦 ea3c60b561231846c824d2ca3ac79d79.png eea3488654586a7e2cdfc3543d9b5b9a.png ▼ 《名企高频考点-C++ STL 二维vector的写法,先行再列和先列再行遍历》 ▼ ps:请在WiFi环境下打开,如果有钱任性请随意

0. 概述

二维数组是日常开发中使用高频的一种管理数据的方式,比如迷宫地图,邻接矩阵等,操作起来也非常方便。在面试中也经常被问到,本文主要对vector构造的二维数组进行说明。

1.传统二维数组的缺陷

传统定义二维数组的方式,采用宏定义给出二维数组的行和列,然后定义出二维数组并对其进行初始化,最后就是对该二维数组进行操作,比如:
#define ROW 5#define COL 5void Test2Array(){  int array[ROW][COL] = { { 0, 1, 0, 0, 0 },                          { 0, 1, 0, 0, 0 },                          { 0, 1, 1, 1, 0 },                          { 0, 1, 0, 1, 0 },                          { 0, 0, 0, 1, 0 } };   // 打印二维数组  for (int i = 0; i < ROW; ++i)  {    for (int j = 0; j < COL; ++j)    {      cout << array[i][j] << " ";    }    cout << endl;  }  cout << endl;  }
该种方式使用起来确实比较方便,但缺陷是:数组被限制死了,只能表示5行5列的数组,但有些情况下需要的可能是动态的二维数组,传统二维数组就无能为力。

2. 使用vector定义二维数组

2.1 矩阵(每行元素个数相同)
(1)元素内容都相同:直接使用vector中vector 来进行构造
int main(){    size_t row, col;    int val;    cin>>row>>col>>val;    // 创建一个row行col列的矩阵,并使用val进行填充    vector<vector<int>> v(row, vector<int>(col, val));    return 0;}

(2)元素内容不同:先创建好矩阵,然后给每行元素依次赋值

int main(){    int row,col;    cin>>row>>col;    // 创建一个row行col列的二维数组,逐个给每行元素进行赋值    vector<vector<int>> v(row, vector<int>(col));    // 将每行的元素赋值为1~col    for(int i = 0; i < v.size(); ++i)    {        for(int j = 0; j < v[i].size(); ++j)        {            v[i][j] = j+1;        }    }    return 0;}

59afc010f124fb39401f970fdc9a8121.png

2.2 动态二维数组
先开辟行,再根据每列中具体元素个数来开辟空间以及给每行元素进行赋值,比如:杨辉三角
/*杨慧三角的前5行0行:11行:1 12行:1 2 13行:1 3 3 14行:1 4 6 4 1观察发现:第0列和对角线全部为1,其余位置为上一行同列元素以及上一行同列前一个元素之和*/void PascalTriangle(int N){  vector<vector<int>> vv;    // 先给出二维数组的行,此时每行还没有空间  vv.resize(N);  for (int i = 0; i < N; ++i)  {        // 将第i行元素个数设置为i+1,初始值用1填充    vv[i].resize(i + 1, 1);    for (int j = 1; j < i; ++j)    {      vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];    }  }    // 打印二维数组  for (int i = 0; i < N; ++i)  {    for (int j = 0; j <= i; ++j)    {      cout<" ";    }    cout << endl;  }}

c33638eabdfa11e67aed2c9b16bacf38.png

2.3 不确定行列个数
该种场景也比较常见,从问题给的描述中只知道结果为二维数组,但是二维数组的行列需要根据题目的输入来确定,直接无法确定。 此种方式的常见解法是:先构造一个空的二维数组,然后构造一个一维的不断向二维数组中插入 例如:二叉树的封层遍历

52987613c9e06321eeaba07a26ceb4e5.png

class Solution {public:    vector<vector<int>> levelOrder(TreeNode* root) {        vector<vector<int>> ret;        if(nullptr == root)            return ret;        queue q;        q.push(root);        while(!q.empty()){            // 为了提高效率,先插入一个空的vector            ret.push_back(vector<int>());            // 拿到数组的最后一行,借助引用直接在最后一行插入            vector<int>& level = ret.back();            // 本层中节点总的个数            size_t size = q.size();            for(int i = 0; i < size; ++i)            {                TreeNode* cur = q.front();                q.pop();                level.push_back(cur->val);                if(cur->left)                    q.push(cur->left);                if(cur->right)                    q.push(cur->right);            }        }        return ret;    }};
2.4 二维数组的误用
用vector创建的二维数组,一般情况下是先给出有多少行,然后再对每行进行操作。最常见的误用就是还没有给每行分配空间,就直接对行进行操作而引起代码崩溃。
void Test2Vector(){  vector<vector<int>> vv;  vv.resize(5);   // 二维数组总共有5行,但是每行现在还没有空间  vv[0][0] = 10;  // 此时直接操作每行中元素时会崩溃}

3. 面试题

二维数组先行后列遍历效率高

还是先列后行遍历效率高?

3.1 先行后列
先行后列是最常见的二维数组的遍历方式,而且效率非常高,因为二维数组的每一行都是一段连续的空间,根据局部性原理,操作系统再访问每个元素时,会将该元素附近多个元素一次性加载到缓存中来提高程序效率。
void Print2Vector(){  // 采用C++11提供的列表初始化构造二维数组,每行元素使用{1,2,3,4,5}进行填充  vector<vector<int>> vv(5, { 1, 2, 3, 4, 5 });  // 常规方式  for (size_t i = 0; i < vv.size(); ++i)  {    for (size_t j = 0; j < vv[i].size(); ++j)    {      cout << vv[i][j] << " ";    }    cout << endl;  }  cout << endl;  // 采用范围for打印  for (auto& rowV : vv){    for (auto e : rowV){      cout << e << " ";    }    cout << endl;  }  cout << endl;}程序输出:1 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 5
3.2 先列后行 该种方式使用比较少,因为效率比较低,一般情况下适合矩阵使用场景。
void Print2Vector2(){  // 采用C++11提供的列表初始化构造二维数组,每行元素使用{1,2,3,4,5}进行填充  vector<vector<int>> vv(5, { 1, 2, 3, 4, 5 });  // 先行后列  for (size_t row = 0; row < vv.size(); ++row)  {    for (size_t col = 0; col < vv[i].size(); ++col)    {      cout << vv[row][col] << " ";    }    cout << endl;  }  cout << endl;  // 先列后行  for (size_t col = 0; col < vv[0].size(); ++col)  {    for (size_t row = 0; row < vv.size(); ++row)    {      cout << vv[row][col] << " ";    }    cout << endl;  }  cout << endl;}程序输出:1 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 1 1 1 12 2 2 2 23 3 3 3 34 4 4 4 45 5 5 5 5

4. 总结

本文主要介绍了vector构造二维数组的常见方式以及遍历,具体如下:

602975df7d5150ab3e34e7b4dc9b4465.png

相信大家对二维数组的使用有进一步的了解,具体还应该根据实际情况选择合适的构造方式。 最后介绍了二维数组行优先遍历以及列优先的遍历方式,以及两种遍历方式的区别,希望通过本文学习,大家对于二维数组应用可以得心应手,谢谢。 作者:时亮益 审核:王海斌 编辑:比特李哥

eaf043b54da45e49654de989f0621e70.png

好看,就要点个"在看"

c8d5caaa9e9ecf3a0038239b75bd519d.gif
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值