在CPP中与2D矢量合作
working with 2d vector in cpp
我的问题是:我有要存储在数据结构中的2D数据。我不知道要提前确切的行和列数。所以,我正在使用2D矢量。我知道(预期的(最大行数和列数。
- 我不想浪费内存,所以我可以使用调整大小功能吗?或
- 如果我与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
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- Linux的Cpp上的计时器
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- 2D数组来自文本输入,中间有空格
- 命名空间中具有.h和.cpp文件的类
- 将值指定给向量(2D)的向量中的某个位置
- 内置函数可查看CPP中的成员变量
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- Cpp-Tuple使用带有变量的get
- 如何使用用户输入在C++中正确填充2D数组
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 有充分的理由在h文件中使用include保护而不是cpp文件吗
- 如何使用 cpp 消除 2d 数组中的边框元素
- 2D 数组在 CPP 中查找行的总和
- 在CPP中与2D矢量合作
- 使用CPP中的迭代器在一排矢量的2D矩阵上迭代
- CSV 文件转换为带换行符的 2D 数组 CPP
- 在cpp中用2d数组保存的列长度
- 将2d std::数组传递给函数cpp