I have defined a struct
struct path{
char type;
bool visit;
bool inPath;
int level;
}
I have also defined a vector of vectors of this type struct
vector < vector<path> > spaceStation(numLevels*levelSize,vector<path> (levelSize));
I have two questions.
1) Have i defined the vector so that the number of rows pertain to (numLevels*levelSize) and columns pertain to levelSize
2) When accessing the individual elements of the vector, how can i set the elements of the struct inside it. I have tried using the .at() member function to little success
Re: 1
Yes. But I can't help feeling like you wanted to do this instead:
vector < vector<path> > spaceStation(numLevels,vector<path> (levelSize))
Note that using the term "rows" and "columns" is entirely in your imagination, concerning vectors. You just have a vector inside another vector. It's like an array of arrays - no special geometry implied.
Re: 2
Because you have a vector of vector, you need to use two indices, not just one:
spaceStation[level][pathindex].visit = true;
Where spaceStation[level] returns the vector at index level, which you then take the element at position pathindex (which is an instance of your struct), and finally modify a value in that struct.
For Q1, you are correct.
For example: a 4x4 dimension vector.
vector< vector< int > > vec(4, vector(4));
For Q2, to access the path, can't you do the following:
spaceStation[2][3] to access row 2 column 3 data, for example.
Then you can do:
spaceStation[2][3].visit to access elements inside your struct.
Related
I'm quite new to coding and am running into a problem. I'm working with matrices and previously I had only integers inside them representing the state of a cell. I initiliazed my grid in the following way:
const int N = 50; // Grid size
// 3 vectors for 3 different antibiotics
std::vector<std::vector<int> > gridAB1(N, std::vector<int>(N));
std::vector<std::vector<int> > gridAB2(N, std::vector<int>(N));
std::vector<std::vector<int> > gridAB3(N, std::vector<int>(N));
After which I would change the 0's in these grids at random positions to a certain value.
Now I'm moving into a more complex setting where cell state can't be defined as easily as just an integer. I will create a class or struct to represent the cells. I was now recommended to have a grid with at positions (unique) pointers pointing to this struct or class. However I'm very unsure of how to initialize this and how to define between empty places in the grid and places with a cell cause only at a few places in the grid should there actually be a pointer pointing to the struct or class, the rest of the grid would just be "empty". If anyone has any tips or ways of achieving something like this that would be great.
If your data is a class/struct named Cell then the analog to your first example would be
#include <memory>
#include <vector>
std::vector<std::vector<std::unique_ptr<Cell>>> grid(N, std::vector<std::unique_ptr<Cell>>(N));
In this case you can "initialize" a Cell by constructing it such as
grid[i][j] = std::make_unique<Cell>(args);
or modify a cell similarly
grid[i][j]->some_method();
Though if your Cell is "simple" (small, POD, trivially copyable and moveable, etc) I would just store by value
std::vector<std::vector<Cell>> grid(N, std::vector<Cell>(N));
Then you'd need some way to determine if the Cell was "filled" yet, like keeping a bool member on the Cell like initialized or something. But the matrix access would look the same
grid[i][j] = Cell(args);
grid[i][j].some_method();
I want to store a list of tiles (pointers to objects of class "Sprite") in a two dimensional vector.
Currently I'm storing all the sprites of my tilemap in a vector.
std::vector<Sprite*> _tiles;
Now I need to get all the neighbored tiles and I thought it be easier, to store my sprites in a 2d matrix (vector in vector) to do those caluclations.
But I can't figure out how to do that.
Header:
private:
std::vector<std::vector<Sprite*>> matrix;
C++ File:
vectorMatrix::vectorMatrix(int columns, int rows) { }
vectorMatrix::~vectorMatrix() { }
void vectorMatrix::addCellAt(int x, int y, Sprite* sprite) {
std::vector< std::vector<Sprite*> > matrix;
matrix[x][y].push_back(sprite);
}
But I get an error message if I use two index operators.
std::vector< std::vector<Sprite*> > matrix;
This is an empty std::vector of of std::vector, and as others have pointed out, it's no longer the data member matrix.
Since it's empty, it's not possible to do matrix[0] - get the first row, matrix[1] - get the second row... You can however allocate the size of the matrix in your constructor first -- e.g. This will give you a rows*columns matrix
vectorMatrix::vectorMatrix(int columns, int rows)
: matrix(rows, std::vector<Sprite*>(columns))
{
}
And then you can set the xth and yth element to the corresponding Sprite*, and of course x and y should be smaller than rows and columns
matrix[x][y] = sprite;
And don't declare matrix again inside the addCellAt, You can use the data members directly anywhere inside the class.
Why do you think it's a good idea to make your matrix a vector-of-vectors? True, this will "work" in the sense that vec_of_vec_matrix[i][j] will return the right thing, but it's somewhat cumbersome and inefficient.
Instead, consider basing your class on a single vector - of all data, as done in this answer (and probably in many libraries). Element access will be something like (for column-major data):
Sprite*& Matrix::operator()(size_t i, size_t j)
{
return mData[i * num_columns + j];
}
You could even arrange with map[x][y] to work, using a row proxy class.
Three problems:
You declare a local variable matrix inside the function, which shadows the member variable.
If the size of the vectors is not set to include the x and y indexes then you will go out of bounds.
matrix[x][y] is not itself a vector, it's an element that you can assign directly:
matrix[x][y] = sprite;
Remember to consider problem 2 before doing this.
so I'm creating a class that implements an adjacency list. Currently in my class definition I initialized two vectors:
vector<vector<int>> adjList;
vector<int> neighbors;
and I declared two functions that I plan to use to make it:
bool constructAdjList();
bool insertIntoAdjList(int, int);
It's getting difficult wrapping my head around 2D vectors. I understand that it is essentially a vector of vectors, but I'm confused about how to insert a new value into one of the "subvectors". For example, I am able to create an adjacency list in createAdjList that is empty with the following loop:
for (int i = 0; i < numOfValues; i++){
neighbors.push_back(0);
adjList.push_back(neighbors);
neighbors.clear();
}
But how can I say, push_back the value 5 to the 4th vector in adjList, which would be represented in my insertIntoAdjList function as
insertIntoAdjList(4, 5);
I know I can access a specific value in a 2D vector by saying adjList[4][1], but how can I push one onto it?
Thanks!
To push on the vector that is an element of another vector, you simply do this
adjList[x].push_back();
If initially you do not have any values in the vector -
You can push values into one vector and then push this vector into the 2D vector.
For example:
vector< vector<int> > vt1;
vector<int> vt2;
vt2.push_back(value);
vt1.push_back(vt2);
If your vector is already populated then -
vt1[index].push_back(value);
A couple of notes here.
Your loop can be significantly shortened just be using the constructors of your two members:
vector<int> neighbors(1, 0); // set to length 1, value is zero
vector<vector<int>> adjList(numOfValues,neighbors); // "outer" vector is numOfValues long
. // each row is a *COPY* of neighbor
If you can't do this at construction time (maybe numOfValues isn't known yet), then there's still a better loop phrasing we can use:
// neighbors object can be reused
neighbors.clear(0);
neighbors.push_back(0);
adjList.reserve(numOfValues); // reserving memory ahead of time will prevent allocations
for (int i = 0; i < numOfValues; i++){
adjList.push_back(neighbors); // push_back is by *COPY*
}
In your example, by using clear and push_back to essentially build the same vector every loop iteration, you are risking an allocation and deallocation each iteration. In practice, most implementations won't do this, but if we can both shorten and potentially make things more efficient, we may as well.
Lastly, if the number of neighbors is relatively small and similar row to row (for instance a finite elements code with tetrahedral elements, where each element connects to ~5 others), then as others have suggested you may be better off with a different structure than vector-of-vector. For instance, a single vector that is logically organized such that a new "row" begins every N elements.
I want to create a vector<vector<int>> where the outer vector is fixed (always containing the same vectors), but the inner vectors can be changed. For example:
int n = 2; //decided at runtime
assert(n>0);
vector<vector<int>> outer(n); //outer vector contains n empty vectors
outer.push_back(vector<int>()); //modifying outer vector - this should be error
auto outer_it = outer.begin();
(*outer_it).push_back(3); //modifying inner vector. should work (which it does).
I tried doing simply const vector<vector<int>>, but that makes even the inner vectors const.
Is my only option to create my own custom FixedVectors class, or are there better ways out there to do this?
by definition,
Vectors are sequence containers representing arrays that can change in
size. Just like arrays, vectors use contiguous storage locations for
their elements, which means that their elements can also be accessed
using offsets on regular pointers to its elements, and just as
efficiently as in arrays. But unlike arrays, their size can change
dynamically, with their storage being handled automatically by the
container.
if you aren't looking to have a data structure that changes in size, a vector probably isn't the best choice for an outer layer, How about using an array of vectors. This way the array is of a fixed size and cannot be modified, while still having the freedom of having its size declared in runtime.
vector<int> *outer;
int VectSize;
cout >> "size of vector array?"
cin >> VectSize;
outer = new vector<int>[VectSize]; //array created with fixed size
outer.push_back() //not happening
Wrap the outer vector into a class which just provides at, begin, end and operator []. Let the class take only have one constructor taking its capacity.
This most probably the best way.
const vector<unique_ptr<vector<int>>> outer = something(n);
For the something, you might write a function, like this:
vector<unique_ptr<vector<int>>> something(int n)
{
vector<unique_ptr<vector<int>>> v(n);
for (auto & p : v)
p.reset(new vector<int>);
return v;
}
I'm building a CSVParser Library (using similar to Excel OLE objects), to be implemented using Vectors
the cell array is saved as a multi dimension string array in the main class CCSVParser
static vector< vector< string> > CellArray;
and another pointer array inside the CRange Class
vector< vector< string> >* RangeCells;
Edit : the purpose of using a pointer array is to save allocated space, since the library may handle large amount of data
inside the GetItem method of CRows class , i need to return a Range object with its pointer array pointing to the addressed row of the main CellArray
CRange* CRows::GetItem(int idxRow)
{
CRange* retRange = new CRange ;
retRange->RangeCells = (vector< vector<string> >*)&CCSVParser::CellArray[idxRow] ;
return retRange;
}
the vector array pointer works fine when pointing to the whole array
retRange->RangeCells = (vector< vector<string> >*)&CCSVParser::CellArray ;
but fails addressing just a row in the CellArray
Note : RangeCells pointer array needs to be multi-dimensional, since in other operations it may return a set of rows
Any ideas how to fulfill this???
Thanks in advance
If CellArray is a vector of vectors (of strings), then CellArray[i] is a vector (of string). However, you try to assigning its address to a pointer to a vector of vectors (of strings) and that is not possible.
The address of a vector is not the same as the address of a vectors of vectors.
RangeCells should be declared as
vector<string> *RangeCells;
I'm guessing it will work much better.