二维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解决各种问题!

相关推荐
Jerry2 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry4 小时前
LeetCode 459. 重复的子字符串
算法
哥不想学算法7 小时前
【C++】字符串字面量拼接
开发语言·c++
海石7 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石7 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry9 小时前
LeetCode 151. 反转字符串中的单词
算法
gugucoding10 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
ChaoZiLL11 小时前
我的数据结构3——链表(link list)
数据结构·链表
a11177611 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜12 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai