Multidimension vector concept C++ - c++

I have a huge 3d vector where I store double values. In order to increase the performance I wanted to reserve the number of elements in advance as I know them before processing;however, I couldn't really figure it out how reserve&clear&erase work in this case.
I have implemented a small program which has 2d vector in this case, pls see the code snippet below:`
for(int counter = 0; counter < 2; counter++){
cout << "Counter-> " << counter << endl;
vector<vector<double> > vec2D;
vec2D.reserve(2);
// assign values to the vec
for(int i = 0; i < 2; i++){
vec2D[i].reserve(5);
for(int j = 0; j < 5; j++){
vec2D[i][j] = j;
}
}
// print the vector content
for(int i = 0; i < 2; i++){
for(int j = 0; j < 5; j++){
cout << vec2D[i][j] << "\t";
}
vec2D[i].clear();
cout << endl;
}
vec2D.clear();
}
When I run this code snippet it iterates thorugh the for loop just for once where it should do it twice; however, when I declare the vector outside of the for loop it does iterate twice. The output of the above snippet is:
Counter-> 0
0 1 2 3 4
0 1 2 3 4
Counter-> 1
Could you please make it clear how it actually should be in this case and how it works.
Thanks in advance.

You have a big problem in your code: reserve() does not change the size of the vector, only its storage capacity (to avoid system calls in the future).
What is needed in your case instead of reserve() is assign() or resize().

If you want any semblance of performance don't use vectors of vectors: this is terribly inefficient. This is probably the most efficient memory utilization, and faster access than vectors, although there are faster solution with some memory trade-offs:
class GridWithSmallDimensions
{
double * values;
int sizeX, sizeY, sizeZ;
public:
GridWithSmallDimensions(int x, int y, int z)
: sizeX(x), sizeY(y), sizeZ(z)
{
values = new double [x*y*z];
}
~ GridWithSmallDimensions()
{
delete [] values;
}
double get(int x, int y, int z)
{
return value[x+sizeX*(y+sizeY*z)];
}
void set(int x, int y, int z, double v)
{
value[x+sizeX*(y+sizeY)] = v;
}
};
Here's a slightly more involved implementation, aimed at reduction of index calculations:
class GridWithRowPointers
{
int sizeX, sizeY, sizeZ; // Dimensions
double * values; // Data
double ** rows; // Pointers to "rows" of data indexed by x
inline int getIndex(y, z) const // Get index of data within a row
{
return sizeZ * y + z;
}
public:
GridWithRowPointers(int x, int y, int z)
: sizeX(x), sizeY(y), sizeZ(z)
{
values = new double [x*y*z]; // Allocate data
rows = new (double*) [x]; // Allocate row pointers
for( int n = 0; n < sizeX; n++ )
{
rows[n] = values + sizeY * sizeZ;
}
}
~ GridWithRowPointers()
{
delete [] values;
delete [] rows;
}
inline double get(int x, int y, int z) const
{
// Access value via row pointer
return rows[ x ][ getIndex(y,z) ];
}
inline void set(int x, int y, int z, double v)
{
// Access value via row pointer
rows[ x ][ getIndex(y,z) ] = v;
}
};

Related

How to pass a 2D arrays of pointers to 3D arrays of pointers (function and class) and return 3d arrays of values in C++?

I am currently working on C++, creating a program of the analysis of matrices.
As far as i saw those can be created using an arrays of arrays like this array2D[3][3]={{1,2,3},{4,5,6},{7,8,9}}.
Therefore, what i did was to generate a function in a class, such a function must return a 2D array. Then i created another class in order to generate the other array of array of arrays, but this 3D arrays need the data obtained by the previous class, remember the previous class holds the values of the matrix in a variable called int **degreesOfFreedom. Here is where the problem arises this second class needs the values of the double pointer and the problem like this appears.
error: cannot convert ‘int***’ to ‘int**’ in assignment
As far as i can see the error comes when trying to pass the 2D pointers arrays into the 3D pointers function.
By the way i already checked several ways and i saw that one of them is replacing the double pointer ** in the declaration of the variable inside of the function, and replace it by [][]. I already tried that, it didn't solve the problem, also i would not like to do that way because in the future i will have matrices of millions per millions elements.
This is my code
#include <iostream>
#include <string>
#include <fstream>
class MatrixOfDegreesOfFreedom
{
public:
int X, Y;
int M = 0;
public:
int **matrixOfDegreesOfFreedom(int rows, int cols)
{
X = rows;
Y = cols;
int** matrix = new int*[X];
for (int i = 0; i < X; ++i)
{
matrix[i] = new int[Y];
for (int j = 0; j < Y; ++j)
{
matrix[i][j] = M;
M = M + 1;
}
}
return matrix;
}
//constructor
MatrixOfDegreesOfFreedom()
{
}
//destructor
~MatrixOfDegreesOfFreedom()
{
}
};
class MatrixOfIndexes
{
public:
int X, Y, Z;
int M = 0;
public:
int ***matrixOfIndexes(int rows, int cols, int colsTwo, int conect[][2], int **DoF)
{
X = rows;
Y = cols;
Z = colsTwo;
int*** matrix = new int**[X];
for (int i = 0; i < X; ++i)
{
M = 0;
matrix[i] = new int*[Y];
for (int j = 0; j < Y; ++j)
{
matrix[i][j] = new int [Z];
for (int t = 0; t < Z; ++t)
{
matrix[i][j][t] = DoF[conect[i][j]][t];
}
M = M + 1;
}
}
return matrix;
}
//constructor
MatrixOfIndexes()
{
}
//destructor
~MatrixOfIndexes()
{
}
};
int main(int argc, char const *argv[])
{
#ifndef OUTPUT
freopen("output.txt", "w", stdout); // file to store the output data.
#endif
int numberOfNodes = 3; // number of nodes
int numberOfDegreesOfFreedomPerNode = 2; //Number of Degrees of Freedom per node
int **degreesOfFreedom = {}; //number of degree of freedom
int numberOfDegreesOfFreedomPerElement = 4; //Number of Degrees of Freedom per element
int numberOfElements = 3;
int connectivity[numberOfElements][2] = {{0,1},{2,1},{0,2}}; // Conectivity matrix along with the property
int **indexes = {};
MatrixOfDegreesOfFreedom tableOfDegreesOfFreedom;
degreesOfFreedom = tableOfDegreesOfFreedom.matrixOfDegreesOfFreedom(numberOfNodes, numberOfDegreesOfFreedomPerNode);
MatrixOfIndexes tableOfIndexes;
indexes = tableOfIndexes.matrixOfIndexes(numberOfElements, numberOfDegreesOfFreedomPerElement, numberOfDegreesOfFreedomPerNode, connectivity, degreesOfFreedom);
std::cout<< "finishing" << std::endl;
return 0;
}
The problem is that the function matrixOfIndexes returns a 3-dimensional pointer (int***) but the array you're assigning that return value to is a two-dimensional one (int**). The types have to match.
To fix it just add an extra * to the declaration of indexes:
int*** indexes = {};

How to print a grid vector in C++

I am working on C++ printing vectors in grid.
Here, I need to put random numbers in a vector size of 3x * 3y. And then I have to print them out with two dimensional matrix with one array.
I do not understand how to represent two dimensional matrix with one array.
In addition, I am not sure how to print out multidimensional vectors. I have to work on print_vector function which prints vectors with grid form.
Could you please help me to improve this code below?
int main()
{
populate_vector();
return 0;
}
void populate_vector()
{
int x,y;
cout<<"Enter two Vectors x and y \n->";
cin>> x;
cin>> y;
srand((unsigned)time(NULL));
std::vector<int> xVector((3*x) * (3*y));
for(int i = 0; (i == 3*x && i == 3*y); ++i){
xVector[i] = rand() % 255 + 1;
if(i == 3*x){
cout << "\n";
}
}
print_vector(xVector);
}
void print_vector(vector<int> &x) {
}
I'm not an expert, but I like to just have a vector of vectors.. something like:
void print_vector(vector<vector<int>>& m_vec)
{
for(auto itY: m_vec)
{
for(auto itX: itY)
cout << itX << " ";
cout << endl;
}
}
void populate_vector()
{
int x,y;
cout << "Enter Two Vectors x and y \n ->";
cin >> x;
cin >> y;
srand((unsigned)time(NULL));
vector<vector <int>> yVector;
for(auto i = 0; i < y*3; ++i)
{
vector<int> xVector;
for(auto j = 0; j < x*3; ++j)
xVector.push_back(rand()%255+1);
yVector.push_back(xVector);
}
print_vector(yVector);
}
EDIT: Ooh, I'd never seen this site before, thanks Saykou... here is the code working: http://cpp.sh/3vzg
Something like this will clarify your code, there is a procedure where the vector is populated, and another one where the vector is printed
int main()
{
int x,y;
std::cout<<"Enter two Vectors x and y \n->";
std::cin>> x;
std::cin>> y;
srand((unsigned)time(NULL));
int xSize = x * 3; // it is important to have the size of the final grid stored
int ySize = y * 3; // for code clarity
std::vector<int> xVector( xSize * ySize);
// iterate all y
for ( y = 0 ; y < ySize; ++y) {
// iterate all x
for ( x = 0 ; x < xSize; ++x) {
// using row major order https://en.wikipedia.org/wiki/Row-_and_column-major_order
xVector[y * xSize + x] = rand() % 255 + 1;
}
}
// when printing you want to run y first
for ( y = 0 ; y < ySize; ++y) {
for ( x = 0 ; x < xSize; ++x) {
// iterate all y
printf("%d ", xVector[y * xSize + x] );
}
printf("\n");
}
}
I think you want to pay attention to this step, where you can convert x and y position into a one array dimension. It's simple you just have to multiply the y by the size of x and add x.
So something like this in two dimensions
1 2 3
4 5 6
will end up in something like this
1 2 3 4 5 6
you can see it running here

C++ vector values keep changing?

This is a real simple problem. I'm writing a sliding block puzzle game for an exercise.
1, 1, 1, 1, 1,
1, 0, 3, 4, 1,
1, 0, 2, 2, 1,
1, 1, 1, 1, 1,
It receives input as in the form above, with '0' representing empty spaces, '1' representing walls, and all other numbers representing blocks.
Here is the class definition and constructor for the game state:
class GameState {
public:
GameState(int hght, int wdth);
GameState(const GameState &obj);
~GameState();
int getHeight();
int getWidth();
int getElem(int i, int j);
void setElem(int i, int j, int val);
void display();
void readFile(char* filename);
bool checkSolved();
map<int, vector<int*> > blockLocations;
vector<int> blockList;
void getBlockLocations();
void findBlock(int n);
private:
int **grid;
int height, width;
void allocate() {
grid = new int*[height];
for(int i = 0; i < height; i++)
{
grid[i] = new int[width];
}
}
};
GameState::GameState(int hght, int wdth) {
height = hght;
width = wdth;
allocate();
for(int i = 0; i < hght; i++) {
for (int j = 0; j < wdth; j++) {
grid[i][j] = 0;
}
}
};
Essentially, the grid is represented by a two-dimensional pointer array of integers. height and width are self-explanatory; blockLocations is a map that maps a block number to its point-wise coordinates of the form (y, x). For the time being, if a block occupies multiple spaces only the lowest rightmost space is listed. The matrix initializes as being nothing but zeros; the actual values are read in from a csv.
All of these methods are defined, but the two methods of concern are getBlockLocations() and findBlock(int n).
void GameState::getBlockLocations() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
blockList.push_back(grid[i][j]);
int pos[2] = {i, j};
vector<int*> v;
v.push_back(pos);
blockLocations[grid[i][j]] = v;
}
}
}
void GameState::findBlock(int n) {
vector<int>::iterator it;
it = find(blockList.begin(), blockList.end(), n);
if (it != blockList.end()) {
vector<int*> * posList = &blockLocations[n];
for (int itr = 0; itr < posList->size(); itr++) {
vector<int*> curPos = *posList;
cout << curPos[itr][0] << ", " << curPos[itr][1] << endl;
}
}
}
The problem comes up when I actually run this. As a case example, when I run getBlockLocations(), it correctly stores the coordinate for '2' as (2, 3). However, when I ask the program to display the location of that block with findBlock(2), the resulting output is something along the lines of (16515320, 0). It's different every time but never correct. I don't see the pointer mistake I'm making to get incorrect values like this.
That is bad:
for (int j = 0; j < width; j++) {
blockList.push_back(grid[i][j]);
int pos[2] = {i, j};
vector<int*> v;
v.push_back(pos);
blockLocations[grid[i][j]] = v;
}
You create a pos variable locally and store its reference. When you go out of scope of the for loop it is invalid / data can be replaced by something else.
(actually as Barmar pointed out, since the pos address is always the same within the loop, the values change at each iteration)
You could use a std::pair<int,int> to store your values instead.
When you insert the pair in the vector, the data is copied, not only the pointer: it is safe.
typedef std::pair<int,int> IntIntPair;
IntIntPair pos(i,j);
std::vector<IntIntPair> v;

Initializing an Array C++

My code is trying to implement the union-find algorithm and I have the id[] array and the sz[] array. I initialize them in the Union-Find constructor, but once I try to use those arrays in the methods within the Union-Find class, it changes all the array values to 1. I don't understand why. Is there something obvious that I'm missing??
H File
class UnionFind{
public:
UnionFind(int size);
void join(int x, int y);
int connected(int x, int y);
int find(int x);
private:
int size;
int id[];
int sz[];
};
CPP File
UnionFind::UnionFind(int size){
this->id[size] = id[size];
for(int i = 0; i < size; i++){
id[i] = i;
}
for(int i = 0; i < size; i++){
sz[i] = 1;
}
}
int UnionFind::find(int l){
//Path Compression Finding the Root
for(int i = 0; i < 5; i++){
}
while(l != id[l]){
id[l] = id[id[l]];
l = id[l];
}
return l;
}
void UnionFind::join(int x, int y){
int m = find(x);
int n = find(y);
if(sz[m] < sz[n]){
id[m] = n;
sz[n] += sz[m];
}
else{
id[n] = m;
sz[m] += sz[n];
}
}
int UnionFind::connected(int x, int y){
if(find(x) == find(y)){
return 1;
}
else{
return 0;
}
}
From the comments.
you can't have int id[] as a class member,
use std::vector (resize and fill in constructor),
your forgot to set member size in constructor,
your find algorithm uses path halving not path compression (this does not affect the running time).
Side note: you can use a single array/vector to implement your disjoint set data structure.

Errors implementing a dynamic matrix class

Alright, I'm trying to implement a simple 2D matrix class right now. This is what it looks like so far:
template <typename Type>
class dyMatrix {
private:
Type *mat;
int width, height;
int length;
public:
dyMatrix (int _width, int _height)
: width(_width), height(_height), mat(0)
{
length = width * height;
mat = new Type[length];
};
// ---
int getWidth() {
return width;
};
int getHeight() {
return height;
};
int getLength() {
return length;
}
// ---
Type& operator() (int i, int j) {
return mat[j * width + i];
};
Type& operator() (int i) {
return mat[i];
};
// ---
~dyMatrix() {
delete[] mat;
};
};
To test it, and compare with static multi-dimensional arrays, I wrote the following snippet of code:
#include <iostream>
using namespace std;
/* matrix class goes here */
struct Coord {
int x, y;
Coord()
: x(0), y(0)
{};
Coord (int _x, int _y)
: x(_x), y(_y)
{};
void print() {
cout << x << ", " << y;
};
};
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
int i = 5, j = 0;
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
adabo(i, j).print();
return 0;
}
"Adabo" and "Inakos" being arbitrarily chosen names. Upon execution, inakos prints its contents but the program crashes before adabo can do anything. Another interesting thing is that, if I give i and j values other than 5 and 0, like 5 and 1, respectively, it works fine.
I don't know what exact numbers work and which make the program go haywire, I only know that there's a irregularity here. What am I possibly doing wrong? I'm an amateur at C++, so I may or not have misused something in any of the structures.
If anyone also has the time, I'd very much like to know if there's any other error of notice in my matrix class. Anything that's not possibly related to the problem, but is a fallacy nevertheless.
I've also tested it with the following main(), but it still crashes after inakos prints its contents in [5][1]. Maybe it has to do not with dyMatrix, but a loosely-implemented Coord?
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
for (int i = 0; i < adabo.getHeight(); i++) {
for (int j = 0; j < adabo.getWidth(); j++) {
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
cout << "; ";
}
cout << "\n\n";
}
cout << "\n\n\n";
Coord temp;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 5; j++) {
temp = adabo(i, j);
temp.print();
cout << "; ";
}
cout << "\n\n";
}
return 0;
}
edit: It hasn't to do with Coord. Just tested with a dyMatrix of ints and static matrix of ints, and it crashes after [5][0] nevertheless.
In your first example, you declared inakos[5][7] so the indices range from 0 to 4 and 0 to 6. inakos[5][0] and inakos[5][1] could therefore crash.
In your second example, you again declare inakos[5][7] yet you let the first index loop from 0 to 6. Again inakos[i][j] can crash. One fix is to switch your indices (ie, change to i<adabo.getWidth() and j<adabo.getHeight()).