As in the subject how create new 2D array in C++?
This code below does not work quite well.
int** t = new *int[3];
for(int i = 0; i < 3; i++)
t[i] = new int[5];
You have a * in the wrong spot. Try:
int **t = new int *[3];
Would vector< vector< int > > work?
You may want to "flatten" the 2D matrix into a 1D array, storing its elements in a convenient container like std::vector (this is more efficient than having a vector<vector<T>>). Then you can map the 2D (row, column) matrix index into the 1D array index.
If you store the elements in the matrix row-wise, you can use a formula like this:
1D array index = column + row * columns count
You can wrap that in a convenient C++ class (overloading operator() for proper matrix element access):
template <typename T>
class Matrix {
public:
Matrix(size_t rows, size_t columns)
: m_data(rows * columns), m_rows(rows), m_columns(columns) {}
size_t Rows() const { return m_rows; }
size_t Columns() const { return m_columns; }
const T & operator()(size_t row, size_t column) const {
return m_data[VectorIndex(row, column)];
}
T & operator()(size_t row, size_t column) {
return m_data[VectorIndex(row, column)];
}
private:
vector<T> m_data;
size_t m_rows;
size_t m_columns;
size_t VectorIndex(size_t row, size_t column) const {
if (row >= m_rows)
throw out_of_range("Matrix<T> - Row index out of bound.");
if (column >= m_columns)
throw out_of_range("Matrix<T> - Column index out of bound.");
return column + row*m_columns;
}
};
Related
Is there a way to implement an operator like [][] for a 1D array?
I want to change the implementation of a 2D vector to a 1D vector in my code (cause this increases the execution speed by about %50 in my program). 2D vector supports [y][x]. How can I have such functionality for a 1D vector?
I can do it like this:
const size_t Y_Axis { 20 };
const size_t X_Axis { 30 };
std::vector<char> vec( Y_Axis * X_Axis );
size_t row { 5 };
size_t col { 28 };
vec[ row * X_Axis + col ] = 't'; // assign a value to a specific row-column
However, typing this formula multiple times throughout a source file seems like violating DRY (don't repeat yourself). How can I do this in an efficient and idiomatic way? I want to hide the complexity and make things a bit abstracted just like operator[][] of 2D vector does.
C++ does not allow virtual containers. So the operator [] is expected to return a true object of the expected size, if you want all the goodies like true iterators to work smoothly.
Here is a post of mine about the iterator question for multi-dimensional containers and a more general question on Code Review
If you only want to build an operator[](int) that returns something that can accept a second [], it can easily be done for a 2D vector, by returning a plain pointer inside the internal data array of a vector:
template <typename T>
class vec2d {
std::vector<T> data;
size_t _cols;
public:
vec2d(int rows, int cols, T* src = nullptr)
: data(rows * cols), _cols(cols) {
if (src != nullptr) {
for (T& val : data) {
val = *src++;
}
}
}
T* operator [] (size_t row) {
return data.data() + row * _cols;
}
const T* operator [] (size_t row) const {
return data.data() + row * _cols;
}
size_t rows() const {
return data.size() / _cols;
}
size_t cols() const {
return _cols;
}
};
And here is an example usage:
int main() {
vec2d<char> v(3, 4, "ABCDEFGHIJKL");
for (size_t i = 0; i < v.rows(); i++) {
for (size_t j = 0; j < v.cols(); j++) {
std::cout << v[i][j] << ' ';
}
std::cout << "\n";
}
}
void Solution::rotate(vector<vector<int> > &A) {
int n= A.size();
int temp[n];
for(int j=0;j<n;j++)
{
temp[j]=A[n-1][j];
}
for(int i=0;i<n-1;i++)
{
A[n-1][i]=A[n-i-1][n-1];
A[n-i-1][n-1] = A[0][n-i-1];
A[0][n-i-1]=A[i][0];
A[i][0]=temp[i];
//A[i+1][0]=A[n-1][i+1];
}
}
I want to call the function again and pass the subarray of original array with starting point as (1,1) of the array and the end point as (n-2,n-2) of the array.
Is it possible to get it done without creating a new vector, i mean just by passing some pointer to the function?
If you just want to look at the submatrix or edit a bounded region in place, make a viewer. The viewer doesn't do anything but restrict the the area of the matrix you are allowed to look at. There is no copying and little extra memory used. This is great if you have, for example, a huge picture and you want to view and manipulate 8x8 element areas.
If you need a new matrix of the given view, teach the viewer to create a new matrix based on the view. There is copying involved in this case, but when you want a copy, copying's hard to avoid.
To demonstrate, first I'm going to wander off the beaten path a bit. If you want this to be fast (and who doesn't want fast?) don't use vector<vector>. A vector is guaranteed to be contiguous in memory, but when you have vectors of vectors that guarantee goes out the window and this leads to poor spatial locality and typically to poor cache usage.
Here is a simple example of a Matrix class that is a bit easier to work with and is all one memory chunk so it tends to be more cache friendly.
// wrapping class for 2D matrixes
class Matrix
{
private:
size_t rows, columns; // large, unsigned datatype. Don't want negative
// indices, so why allow them?
std::vector<int> matrix; // 1D vector. Simple and easy to handle.
// also often much faster than vector of vectors
// due to improved spatial locality helping
// predictability of data access
public:
// build zero-filled Matrix
Matrix(size_t numrows, size_t numcols) :
rows(numrows), columns(numcols), matrix(rows * columns)
{
}
// 2D to 1D mapping accessor
int & operator()(size_t row, size_t column)
{
// check bounds here
return matrix[row * columns + column];
}
// 2D to 1D mapping accessor for constant Matrix
int operator()(size_t row, size_t column) const
{
// check bounds here
return matrix[row * columns + column];
}
// dimension accessors
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
};
Now that we have a faster, nicely contained Matrix class we can make a really simple MatrixView class.
class MatrixView
{
size_t mStartRow; // view offset in row
size_t mStartColumn; // view offset in column
size_t mRows; // number of viewed rows
size_t mColumns; // number of viewed columns
Matrix & mMat; // viewed Matrix
public:
// using start and endpoints in this constructor. A more ideologically correct
// constructor would behave the same as the standard library and take offset
// and length as parameters.
MatrixView(size_t startrow,
size_t startcolumn,
size_t endrow,
size_t endcolumn,
Matrix & mat):
mStartRow(startrow),
mStartColumn(startcolumn),
mRows(endrow - startrow),
mColumns(endcolumn - startcolumn),
mMat(mat)
{
//ensure dimensions make sense
if (startrow > endrow ||
startcolumn > endcolumn ||
mRows > mat.getRows() ||
mColumns > mat.getColumns())
{
throw std::runtime_error("Bad MatrixView dimensions");
}
}
int & operator()(size_t row, size_t column)
{
// check bounds here if you want to
// look at the source matrix plus offsets
return mMat(row+mStartRow, column+mStartColumn);
}
// 2D to 1D mapping accessor for constant Matrix
int operator()(size_t row, size_t column) const
{
// check bounds here if you want to
return mMat(row+mStartRow, column+mStartColumn);
}
// dimension accessors
size_t getRows() const
{
return mRows;
}
size_t getColumns() const
{
return mColumns;
}
// build a new Matrix based on this view
Matrix clone()
{
Matrix result(mRows, mColumns);
for (size_t row = 0; row < mRows; ++row)
{
for (size_t col = 0; col < mColumns; ++col)
{
result(row, col) = mMat(row+mStartRow, col+mStartColumn);
}
}
return result;
}
};
And an example of using this sucker:
// stream formatters
std::ostream & operator<<(std::ostream & out, const Matrix & mat)
{
for (size_t row = 0; row < mat.getRows(); ++row)
{
for (size_t col = 0; col < mat.getColumns(); ++col)
{
std::cout << std::setw(5) << mat(row, col);
}
std::cout << '\n';
}
return out;
}
std::ostream & operator<<(std::ostream & out, const MatrixView & mat)
{
for (size_t row = 0; row < mat.getRows(); ++row)
{
for (size_t col = 0; col < mat.getColumns(); ++col)
{
std::cout << std::setw(5) << mat(row, col);
}
std::cout << '\n';
}
return out;
}
int main()
{
Matrix one(6, 6); // make 6x6 matrix
int count = 0;
// set inputs to make errors really stand out
for (size_t row = 0; row < one.getRows(); ++row)
{
for (size_t col = 0; col < one.getColumns(); ++col)
{
one(row, col) = count++;
}
}
// print initial matrix
std::cout << one << '\n';
// make a view of matrix that leaves off the outside.
MatrixView view(1,1,5,5, one);
// print the view
std::cout << view << '\n';
// get a clone of the view we can pass into a function
Matrix clone = view.clone();
// and print the clone
std::cout << clone << '\n';
}
I am trying to implement Strassen's algorithm for matrix multiplication in C++, and I want to find a way to split two matrices into four parts each in constant time. Here is the current way I am doing so:
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
A11[i][j] = a[i][j];
A12[i][j] = a[i][j+n];
A21[i][j] = a[i+n][j];
A22[i][j] = a[i+n][j+n];
B11[i][j] = b[i][j];
B12[i][j] = b[i][j+n];
B21[i][j] = b[i+n][j];
B22[i][j] = b[i+n][j+n];
}
}
This approach is obviously O(n^2), and it adds n^2*log(n) to the runtime, as it is called for each recursive call.
It seems that the way to do this in constant time is to create pointers to the four sub-matrices, rather than copy over the values, but I am having a difficult time figuring out how to create those pointers. Any help would be appreciated.
Don't think of matrices, think of matrix views.
A matrix view has pointer to a buffer of T, a width, a height, an offset, and a stride between columns (or rows).
We can start with an array view type.
template<class T>
struct array_view {
T* b = 0; T* e = 0;
T* begin() const{ return b; }
T* end() const{ return e; }
array_view( T* s, T* f ):b(s), e(f) {}
array_view( T* s, std::size_t l ):array_view(s, s+l) {}
std::size_t size() const { return end()-begin(); }
T& operator[]( std::size_t n ) const { return *(begin()+n); }
array_view slice( std::size_t start, std::size_t length ) const {
start = (std::min)(start, size());
length = (std::min)(size()-start, length);
return {b+start, length};
}
};
Now our matrix view:
temlpate<class T>
struct matrix_view {
std::size_t height, width;
std::size_t offset, stride;
array_view<T> buffer;
// TODO: Ctors
// one from a matrix that has offset and stirde set to 0.
// another that lets you create a sub-matrix
array_view<T> operator[]( std::size_t n ) const {
return buffer.slice( offset+stride*n, width ); // or width, depending on if row or column major
}
};
Now your code does work on matrix_views, not matrices.
You could create a submatrix class that holds the location in the parent matrix of the smaller matrix you want to use. Mostly just what you already have for your Matrix, except you'd need to store starting indexes for the row and columns, then offset your indexing by those offsets. If done right the main/root matrix would be a submatrix with the full matrix as the bounds.
I have a std::vector of std::vectors and I want to use a for loop to push back one element to each inner vector. The code looks like this, but clearly does not work because you cannot access each of the vectors in that way (matrix[i] =) and line 8 produces a Segmentation Fault .
std::vector<std::vector<float> > matrix;
for (size_t j = 0; j < number_of_columns; ++j) {
vector<float> elements_to_push = compute_elements();
for (size_t i = 0; i < number_of_rows; ++i) {
matrix[i].push_back(elements_to_push[i]);
}
}
So, I would like to write the elements column-wise. Writing row-wise is not an option for me because I need to use some external functions that expect the elements to be in that order.
I think that a solution involves using a vector of pointers (std::vector<float*>) but I would like to know if it is possible to do it using vectors only as this simplifies things.
Also, it would be the best if the solution does not involve C++11 or later functionality because I have to keep backwards compatibility. However, if you have an answer that uses C++11 or later you can still write it for anyone else who might find it useful.
It would be easier if you computed and pushed rows instead of columns. However here is a solution (since you already know the size of matrix):
std::vector<std::vector<float> > matrix(number_of_rows, std::vector<float>(number_of_columns, float()));
for (size_t j = 0; j < number_of_columns; ++j) {
vector<float> elements_to_push = compute_elements();
for (size_t i = 0; i < number_of_rows; ++i) {
matrix[i][j] = elements_to_push[i];
}
}
I recommend creating a wrapper around a single std::vector in row-major configuration to represent your matrix, making it more convenient to work with than a 2D std::vector. The following should be compatible with pre-c++11 which is why I haven't used auto and some other c++11 onwards features...
template<typename Ty>
class matrix {
// enables use of [][] on matrix objects
class proxy_row_vector {
public:
proxy_row_vector(std::vector<Ty>& _vec, std::size_t cols, std::size_t row_ind)
: vec(_vec), columns(cols), row_index(row_ind) {}
const Ty& operator[](std::size_t col_ind) const {
return vec[row_index*columns + col_ind];
}
Ty& operator[](std::size_t col_ind) {
return vec[row_index*columns + col_ind];
}
private:
std::vector<Ty>& vec;
std::size_t row_index;
std::size_t columns;
};
public:
// construct rows*cols matrix with default-inserted Ty instances
explicit matrix(std::size_t rows, std::size_t cols)
: mtx(rows*cols), rows_(rows), cols_(cols) {}
std::size_t rows() const { return rows_; }
std::size_t columns() const { return cols_; }
// used for const [][] access
proxy_row_vector operator[](std::size_t row_ind) const {
return proxy_row_vector(mtx, cols_, row_ind);
}
// used for mutable [][] access
proxy_row_vector operator[](std::size_t row_ind) {
return proxy_row_vector(mtx, cols_, row_ind);
}
// insert a new row at the end
void push_row(const std::vector<Ty>& row_vec) {
for (std::vector<Ty>::iterator it = row_vec.begin(); it < row_vec.end(); ++it)
mtx.push_back(*it);
++rows_;
}
// insert a new column at the end
void push_column(const std::vector<Ty>& col_vec) {
insert_column(cols_, col_vec);
}
// insert a row at indicated position
void insert_row(size_type row_pos, const std::vector<Ty>& row_vec) {
mtx.insert(mtx.begin() + row_pos*cols_, row_vec.begin(), row_vec.end());
++rows_;
}
// insert a column at indicated position
void insert_column(size_type col_pos, const std::vector<Ty>& col_vec) {
for (std::size_t i = 0; i < col_vec.size(); ++i) {
mtx.insert(mtx.begin() + i*(cols_+1)+col_pos,col_vec[i]);
}
++cols_;
}
private:
std::vector<Ty> mtx;
std::size_t rows_;
std::size_t cols_;
};
Then pushing a new column is simple, using your example:
matrix<float> mat;
std::vector<float> column_to_push = compute_elements();
mat.push_column(column_to_push);
Note: In the matrix class above there is no bounds or size checking as it is a minimal example of such a class. You should add size checking in the row/column inserting methods to avoid trying to push a row vector or column vector which exceeds (or falls short of) the current number of columns or rows of the matrix respectively. Additionally you would probably want to add iterator support (trivial via std::vector iterators) and other methods (e.g. erasing rows/columns).
i've got a Class Image with a member called buffer, a vector of unsigned char that store the pixels of image. I'd like to handle this buffer as a matrix.i'd like to access to the buffer as img[ i ][ j ] but i've not idea how? anyone can suggest me a solution?
here's my tentative:
unsigned char * &Image::operator[](int i) {
return buffer[ rows+i ]
}
i read this post then i think that is possible. my class is like that:
class Image {
private:
unsigned char * buffer;
int buf_size;
int rows;
int cols;
Phisical_img_manager phisical_img_manager;
const char * in_img_filename;
public:
unsigned char * & operator[](int i);
Image(const char * in_img_filename);
unsigned char * get_buffer();
int get_cols();
int get_rows();
};
Solution
You could do it in row-major order as below:
class Image {
int rows, cols;
unsigned char *buffer;
public:
// ...
unsigned char* operator[](int const i) { return &(buffer[i * cols]); }
unsigned char const* operator[](int const i) const { return &(buffer[i * cols]); }
};
Live Demo
Discussion
Your buffer is a contiguous block of memory. Of size N = rows * cols.
However the notion of an image is a set of pixels arranged in a 2D construct/matrix:
What we want is to arrange this 2D construct in the 1D buffer in computer's memory. We can do this in two ways:
Row major order.
Column major order.
In row major order we store each row of the image one after the other. That is, for the following size 2x2 image
the respective buffer storage would look like:
In column major order we store each column of the image one after the other. That is, the buffer storage for the same size 2x2 image would look like:
Programming languages that support multi-dimensional arrays either implement row-major or column-major storage order for them. In C and C++ row-major order is used.
In the code showed above we implement row-major order. We define an overloaded subscript operator that takes as input the row index (e.g., i) we want to access. Multiplying this i with the number of columns we get the starting index of the ith row in the image. We return the address of the element that lies in this specific address. This address marks the beginning of a sub-array of the original buffer as well as the beginning of the ith row. To clarify further see the following code example:
Image I(2, 3);
I[1][2] = 42;
calling I[1][2] = 42 is like calling:
(I.operator[](1))[2];
sub-call I.operator[](1) returns a pointer to the address where the second row of the image starts. Then we use this returned pointer as an ordinary dynamic allocated array. In this specific example we add 2 to this pointer (i.e., that is what [2] does) and thus we get the element of the row that lies 2 positions after the first element of the row (i.e., the third element of the second row of the image).
Alternative Solution For C++11
If your compiler supports C++11 and smart pointers you could do the following scheme in order to avoid memory management. Furthermore I would overload operator()(std::size_t const, std::size_t const) because overloading as above you expose the buffer and thus you're hurting encapsulation:
class Image {
int rows, cols;
std::unique_ptr<unsigned char[]> buffer;
public:
Image(int const rows_ = 0, int const cols_ = 0)
: rows(rows_), cols(cols_), buffer(new unsigned char[rows * cols]) {}
Image(Image const &other)
: rows(other.rows), cols(other.cols), buffer(new unsigned char[rows * cols]) {
std::copy(other.buffer.get(), other.buffer.get() + (rows * cols), buffer.get());
}
Image(Image &&other)
: rows(other.rows), cols(other.cols), buffer(std::move(other.buffer)) {
other.rows = 0;
other.cols = 0;
}
unsigned char& operator()(std::size_t const i, std::size_t const j) {
return buffer[cols * i + j];
}
unsigned char const& operator()(std::size_t const i, std::size_t const j) const {
return buffer[cols * i + j];
}
Image& operator=(Image const &other) {
rows = other.rows;
cols = other.cols;
buffer.reset(new unsigned char[rows * cols]);
std::copy(other.buffer.get(), other.buffer.get() + (rows * cols), buffer.get());
return *this;
}
Image& operator=(Image &&other) {
rows = other.rows;
cols = other.cols;
buffer.swap(other.buffer);
other.rows = 0;
other.cols = 0;
return *this;
}
// ...
};
Live Demo