在CPP中与2D矢量合作

working with 2d vector in cpp

本文关键字:2D CPP 中与      更新时间:2023-10-16

我的问题是:我有要存储在数据结构中的2D数据。我不知道要提前确切的行和列数。所以,我正在使用2D矢量。我知道(预期的(最大行数和列数。

  1. 我不想浪费内存,所以我可以使用调整大小功能吗?或
  2. 如果我与1D矢量一起使用并以2D访问(例如,vector [row * row *( 宽度 col](。我如何找到矢量的宽度?

关于您在第一个选项中尝试访问的方式,它不能完成。在分配之前,您需要已经有一个值。下面的代码显示了人为但功能的解决方案和演示。

#include <vector>
#include <iostream>
using namespace std;
void add_element(vector<vector<int>> &data, int row, int col, int val)
{
    while (data.size() <= row) data.push_back(vector<int>());
    while (data[row].size() <= col) data[row].push_back(int());
    data[row][col] = val;
}
int main()
{
    vector<vector<int>> data;
    int col_idx = 0;
    cout << "Before...n";
    cout << data.size() << " rows.nn";
    for (auto &row : data)
        cout << "row " << col_idx++ << ": " << row.size() << " columns.n";
    add_element(data, 4, 5, 21);
    cout << "After...n";
    col_idx = 0;
    cout << data.size() << " rows.nn";
    for (auto &row : data)
        cout << "row " << col_idx++ << ": " << row.size() << " columns.n";
    cout << "nAccess...n";
    cout << "data[4][5] == " << data[4][5] << endl;
    data[4][5] = 99;
    data[2].push_back(33);
    data[2].push_back(41);
    data[2].push_back(55);
    cout << "data[2][2] == " << data[2][2] << endl;
    data[2][2] *= 2;
    cout << "data[2][2] == " << data[2][2] << endl;
    cout << "data[4][5] == " << data[4][5] << endl;
    return 0;
}

使用 resize()函数使用 std::vector::reserve()代替单个行。

std::vector< std::vector<int> > data;
data.resize(nMaxRows);
for(int i=0;i<nMaxRows;i++){
    data[i].reserve(nMaxColumn);
}

对于选项2

class Vector2D{
    private:
        vector<int> m_data;
        unsigned int m_width;
        unsigned int m_height;
        unsigned int index_transformation((const unsigned int i, const unsigned int j) const;
    public:
        Vector2D(const int default_value = 0);
        Vector2D(const unsigned int width, const unsigned int height, const int default_value = 0);
        void resize(const unsigned int width, const unsigned int height);
        int& operator() (const unsigned int i, const unsigned int j);
        const int& operator() (const unsigned int i, const unsigned int j) const;
        const unsigned int& width() const;
        const unsigned int& height() const;
}

(在我的示例中首先完成私人,以便您轻松理解结构(

点是,首先或高度的宽度是任意的,而这样做的责任应该躺在一个地方,例如包装器中。在这种情况下,它甚至还原为单个方法,index_transformation。

编辑:安迪(Andy T(问我为什么我喜欢这种结构,这是,我不喜欢。基本上,我要说的如果您这样做,那么...但是您可以轻松使用vector<vector<int> >,而没有问题。也就是说,您可能还需要包装一个2D向量,其简单原因可以确保向量保持规律(与{{1,2}不同,例如2和长度为1( - 也就是说,如果向量经常传递。在一个小范围内或任何可以轻松确保规律性的情况下,简单的2D向量是完全可以的。

也就是说,对于您的问题而言:最有可能的初始化不会受到伤害。也就是说,您可以简单地用预期的元素初始化矢量(或者更好地说的是其中的上边界(。当然,这将导致O(n(的工作量,但是与后来的工作量相比,此工作负载很小。如果不是这样,因为您的期望可能比实际用法更大,或者在以后的算法中只做少数操作,是的,请使用储备金,在这里没问题。缺点是您仍然需要调整可能忘记的向量大小,但这很容易检测到。

在评论中讨论后,问题似乎是在不存在的情况下访问2D向量项目。

设置具有任意索引的项目:

template <typename T>
void set(std::vector<std::vector<T>>& vec, size_t i, size_t j, T const& val)
{
    if (vec.size() <= i)
        vec.resize(i + 1);
    auto&& row = vec[i];
    if (row.size() <= j)
        row.resize(j + 1);
    row[j] = val;
}

要获取一个项目,您需要确定想要的行为:在不存在该项目或使用默认值创建并返回时,要引发异常。

您询问有关释放未使用的内存的问题。您只能在向量末尾释放内存,因为其所有项目都将其存储在一个接一个地存储在一个内存块中。如果您的数据结构稀疏(有很多差距(,则vector不是最好的候选人。最简单的解决方案是通过map模拟稀疏容器,例如std::map<size_t, std::map<size_t, T>>。在这种情况下,当您做

map[i][j] = val;

即使在(i, j) Place上的项目在按需创建之前就不存在。要免费记忆,您需要通过std::map<Key, Value>::erase(key)(http://www.cplusplus.com/reference/mmap/map/map/erase/(删除地图上的项目

您可以使用矩阵:

#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
#include <iostream>
#include <initializer_list>
#include <stdexcept>
#include <sstream>
using namespace std;
template<typename T>
class Matrix {
public:
    typedef T value_type;
    typedef vector<T> row_t;
    // ctor
    Matrix(){}  
    Matrix(int rows, int cols){
        for (int i = 0; i<rows; ++i){
            mat.push_back(row_t(cols));
        }
    }
    Matrix(int rows, int cols, const initializer_list<T>& l){
        for (int i = 0; i<rows; ++i){
            mat.push_back(row_t(cols));
        }
        auto it = l.begin();
        int y=0, x=0;
        while (it != l.end()){
            mat[y][x++] = *it++;
            if (x == cols){
                ++y;
                x = 0;
            }
        }
    }
    Matrix(const Matrix<T>& m){
        for (auto e : m.mat){
            mat.push_back(e);
        }
    }
    // method
    int getRowCount(){
        return mat.size();
    }
    int getColumnCount(){
        if (mat.size() == 0)
            return 0;
        return mat[0].size();
    }
    row_t& operator[](int n){
        if ( n<0 || static_cast<size_t>(n) >= mat.size() ){
            ostringstream oss;
            oss << "bad index " << n << " out of range [0.." << mat.size() << "]";
            throw runtime_error(oss.str());
        }
        return mat[n];
    }
    Matrix<T>& operator=(const Matrix<T>& m){
        if (&m != this){
            mat.clear();
            for (auto e : m.mat){
                mat.push_back(e);
            }
        }
        return *this;
    }
private:
    vector<row_t> mat;
};
#endif // MATRIX_H