在cpp中使用2d矢量

时间:2017-04-21 10:11:41

标签: c++ vector

我的问题是: 我有2d数据,我想存储在数据结构中。我事先并不知道确切的行数和列数。 所以, 我正在使用2D矢量。 我知道(Anticipated)最大行数和列数。

  1. 我不想浪费内存,所以我可以使用调整大小功能吗? 或者
  2. 如果我使用1D矢量并将其作为2D访问(例如矢量[行*]     width + col])。我怎样才能找到载体的宽度?

5 个答案:

答案 0 :(得分:1)

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

#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.\n\n";
    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.\n\n";
    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;
}

答案 1 :(得分:0)

使用std::vector::reserve()resize()功能来保留各行。

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

答案 2 :(得分:0)

对于选项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> >而不是问题。也就是说,你可能还想包装一个二维矢量,原因很简单,这可以确保矢量保持规则(例如,不像{{1,2},{3}},它有一个长度为子的向量2和长度1)之一 - 即,如果向量传递很多。简单的2d向量在小范围内或在任何可以轻松确保规律性的上下文中都是完全正确的。

那就是说,对于你的问题:最有可能的是,初始化不会受到伤害。也就是说,您可以使用预期的元素数量(或者更好地说,它的上边界)初始化矢量。这当然会导致O(n)中的工作负载,但最有可能的是,与之后的工作负载相比,此工作负载会很小。如果不是,因为你的预期可能比实际使用量大得多,或者如果在后面的算法中只做了一些动作,是的,请保留,这里没问题。缺点是你仍然需要调整你可以忘记的矢量大小,但这很容易被发现。

答案 3 :(得分:0)

在评论中讨论后,问题是当它们还不存在时访问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)处的某个项目在按需创建之前不存在。要释放未使用的内存,您需要通过std::map<Key, Value>::erase(key)UI just shows the root environment!

从地图中删除项目

答案 4 :(得分:-1)

您可以使用矩阵:

#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