二维vector完全指南1:从定义到增删改查

1. 定义和初始化

1.1 空二维vector

复制代码
#include <vector>
using namespace std;

vector<vector<int>> vec2d;  // 完全空的二维vector

1.2 指定行数

复制代码
vector<vector<int>> vec2d(3);  // 3行,每行是空的vector

1.3 指定行数和列数

复制代码
vector<vector<int>> vec2d(3, vector<int>(4));        // 3行4列,初始为0
vector<vector<int>> vec2d(3, vector<int>(4, -1));    // 3行4列,初始为-1

1.4 使用初始化列表(C++11)

复制代码
vector<vector<int>> vec2d = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

2. 添加元素

2.1 添加行

复制代码
vector<vector<int>> vec2d;

// 方法1:添加空行,然后添加元素
vec2d.push_back(vector<int>());  // 添加空行
vec2d[0].push_back(1);          // 在第一行添加元素
vec2d[0].push_back(2);

// 方法2:直接添加一行元素
vec2d.push_back({3, 4, 5});     // 添加第二行,包含3个元素

// 方法3:使用emplace_back(C++11,效率更高)
vec2d.emplace_back(6, 7, 8);    // 添加第三行

2.2 在特定位置插入行

复制代码
vector<vector<int>> vec2d = {{1,2}, {3,4}};

// 在第一行前面插入新行
vec2d.insert(vec2d.begin(), {5, 6, 7});

// 在第二行前面插入新行
vec2d.insert(vec2d.begin() + 1, {8, 9});

2.3 在特定行添加元素

复制代码
vector<vector<int>> vec2d = {{1,2}, {3,4}};

vec2d[0].push_back(10);     // 第一行末尾添加10 → {1,2,10}
vec2d[1].push_back(20);     // 第二行末尾添加20 → {3,4,20}

// 在行内特定位置插入
vec2d[0].insert(vec2d[0].begin() + 1, 15);  // 第一行第二个位置插入15 → {1,15,2,10}

3. 访问元素

3.1 使用下标访问

复制代码
vector<vector<int>> vec2d = {{1,2,3}, {4,5,6}, {7,8,9}};

int element = vec2d[1][2];  // 访问第二行第三列 → 6
vec2d[0][1] = 10;          // 修改第一行第二列 → 10

3.2 使用at()访问(更安全,会检查边界)

复制代码
vector<vector<int>> vec2d = {{1,2,3}, {4,5,6}};

try {
    int element = vec2d.at(1).at(2);  // 6
    vec2d.at(0).at(1) = 10;           // 修改元素
} catch (const out_of_range& e) {
    cout << "索引越界!" << endl;
}

3.3 遍历二维vector

复制代码
vector<vector<int>> vec2d = {{1,2,3}, {4,5,6}, {7,8,9}};

// 方法1:使用下标遍历
for (int i = 0; i < vec2d.size(); i++) {
    for (int j = 0; j < vec2d[i].size(); j++) {
        cout << vec2d[i][j] << " ";
    }
    cout << endl;
}

// 方法2:使用范围for循环(C++11)
for (const auto& row : vec2d) {
    for (int element : row) {
        cout << element << " ";
    }
    cout << endl;
}

// 方法3:使用迭代器
for (auto row_it = vec2d.begin(); row_it != vec2d.end(); row_it++) {
    for (auto col_it = row_it->begin(); col_it != row_it->end(); col_it++) {
        cout << *col_it << " ";
    }
    cout << endl;
}

4. 删除元素

4.1 删除行

复制代码
vector<vector<int>> vec2d = {{1,2}, {3,4}, {5,6}};

vec2d.pop_back();           // 删除最后一行 → 剩下{{1,2}, {3,4}}
vec2d.erase(vec2d.begin()); // 删除第一行 → 剩下{{3,4}}
vec2d.erase(vec2d.begin() + 1, vec2d.end()); // 删除第一行之后的所有行

4.2 删除行内元素

复制代码
vector<vector<int>> vec2d = {{1,2,3}, {4,5,6}};

vec2d[0].pop_back();        // 删除第一行最后一个元素 → {1,2}
vec2d[1].erase(vec2d[1].begin() + 1); // 删除第二行第二个元素 → {4,6}

4.3 清空

复制代码
vector<vector<int>> vec2d = {{1,2}, {3,4}};

vec2d.clear();              // 清空所有行
vec2d[0].clear();           // 清空第一行的所有元素

5. 修改大小

5.1 调整行数

复制代码
vector<vector<int>> vec2d = {{1,2}, {3,4}};

vec2d.resize(5);           // 扩展到5行,新行是空的
vec2d.resize(3);           // 缩减到3行,多余行被删除

5.2 调整列数

复制代码
vector<vector<int>> vec2d = {{1,2}, {3,4}};

vec2d[0].resize(5, -1);    // 第一行扩展到5列,新元素初始为-1 → {1,2,-1,-1,-1}
vec2d[1].resize(1);        // 第二行缩减到1列 → {3}

6. 实用操作

6.1 获取大小信息

复制代码
vector<vector<int>> vec2d = {{1,2,3}, {4,5}};

int rows = vec2d.size();                   // 行数:2
int cols_row0 = vec2d[0].size();           // 第一行的列数:3
bool empty = vec2d.empty();                // 是否为空:false
bool row0_empty = vec2d[0].empty();        // 第一行是否为空:false

6.2 交换

复制代码
vector<vector<int>> vec1 = {{1,2}, {3,4}};
vector<vector<int>> vec2 = {{5,6,7}, {8,9}};

vec1.swap(vec2);  // 交换两个二维vector
swap(vec1[0], vec1[1]);  // 交换两行

6.3 判断是否相等

复制代码
vector<vector<int>> vec1 = {{1,2}, {3,4}};
vector<vector<int>> vec2 = {{1,2}, {3,4}};

if (vec1 == vec2) {
    cout << "两个二维vector相等" << endl;
}

7. 分组背包问题的实际应用

复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int v, n, t;
    cin >> v >> n >> t;
    
    // 定义二维vector存储重量和价值
    vector<vector<int>> w(t+1), c(t+1);
    
    // 读取数据并动态添加
    for (int i = 0; i < n; i++) {
        int weight, value, group;
        cin >> weight >> value >> group;
        
        // 动态添加到对应组
        w[group].push_back(weight);
        c[group].push_back(value);
    }
    
    // 使用一维DP数组(推荐用于分组背包)
    vector<int> dp(v+1, 0);
    
    // 分组背包核心算法
    for (int i = 1; i <= t; i++) {
        // 倒序遍历容量,确保每组只选一个
        for (int j = v; j >= 0; j--) {
            // 遍历当前组的每个物品
            for (int k = 0; k < w[i].size(); k++) {
                if (j >= w[i][k]) {
                    dp[j] = max(dp[j], dp[j - w[i][k]] + c[i][k]);
                }
            }
        }
    }
    
    cout << dp[v] << endl;
    return 0;
}

8. 重要注意事项

  1. 边界检查 :使用at()[]更安全,但性能稍差

  2. 内存管理:vector会自动管理内存,无需手动释放

  3. 性能考虑 :如果知道大致大小,使用reserve()预分配空间

  4. 不规则二维数组:每行可以有不同数量的元素

这个指南涵盖了二维vector的所有基本操作,掌握了这些就能熟练使用二维vector解决各种问题!

相关推荐
再卷也是菜1 小时前
C++篇(22)LRU Cache
数据结构·c++·算法
语落心生1 小时前
海量数据集的AI自动化预测打标 -- 振动特征多标签分类
算法
语落心生1 小时前
海量数据集AI自动化打标 - 温度周期检测
算法
语落心生1 小时前
海量数据集的AI自动化预测打标 -- 矿业音频分类
算法
吃着火锅x唱着歌1 小时前
LeetCode 3185.构成整天的下标对数目II
算法·leetcode·职场和发展
D_evil__1 小时前
[C++高频精进] 现代C++特性:Lambda表达式
c++
程序猿多布1 小时前
数据结构 之 栈和队列
数据结构··队列
鱼鱼块1 小时前
《最小栈的巧妙设计:用辅助栈实现 O(1) 获取最小值》
javascript·算法·面试
San301 小时前
反转字符串与两数之和:两道简单题背后的 JavaScript 思维深度
javascript·算法·面试