Push_back 1D Vector as Row into 2D Vector Array - c++

I'm trying to define the values of a 'row' or 1D vector and then push_back that row into a 2D vector. I've tried a couple different things that don't throw errors but also don't seem to work. Code below:
#include <vector>
#include <iostream>
using std::vector;
#define HEIGHT 5
#define WIDTH 3
// 2D VECTOR ARRAY EXAMPLE
int main() {
vector<vector<double> > array2D;
vector<double> currentRow;
// Set up sizes. (HEIGHT x WIDTH)
// 2D resize
array2D.resize(HEIGHT);
for (int i = 0; i < HEIGHT; ++i)
{
array2D[i].resize(WIDTH);
}
// Try putting some values in
array2D[1][2] = 6.0; // this works
array2D[2].push_back(45); // this value doesn't appear in vector output. Why?
// 1D resize
currentRow.resize(3);
// Insert values into row
currentRow[0] = 1;
currentRow[1] = 12.76;
currentRow[2] = 3;
// Push row into 2D array
array2D.push_back(currentRow); // this row doesn't appear in value output. Why?
// Output all values
for (int i = 0; i < HEIGHT; ++i)
{
for (int j = 0; j < WIDTH; ++j)
{
std::cout << array2D[i][j] << '\t';
}
std::cout << std::endl;
}
return 0;
}

By the time you push_back currentRow, array2D already contains HEIGHT rows and after the push_back it will contain HEIGHT+1 rows. You just don't show the last one you added, only the first HEIGHT rows.

push_back() appends an item to the end of the vector. If the vector contained WIDTH items, it contains WIDTH+1 items after the push_back().
When you print the contents of the vector, you only print the first WIDTH items, even if the vector contains more, so you don't see the additional items.
You can find out how many items are in a vector with the size() method.

You are using resize when you actually want to use reserve method instead. The thing is that resize does change the content of the vector, while reserve just changes the storage capacity. So if you resize a vector to N elements and then push some elements into it, they will be pushed in positions N, N + 1, etc, while if you just reserve size for N elements, they will be pushed in positions 0, 1, etc, which is what you seem to want.

Related

How to extract columns of a 2D array in c++?

My task is to count the no of elements greater than an element aij in the corresponding row i and column j for every element of a 2D array in C++. My way is to extract the ith row and jth column, sort them and traverse the sorted array with a counter variable until aij element is found.
But the problem is in extracting the entire row i and entire column j for every such element. I know that the row can easily be extracted with std::copy function in c++.
int **adj=new int *[n];
for(r=0;r<m;r++)
for(c=0;c<n;c++)
cin>>adj[r][c];
int buf[n];
std::copy(adj[i], adj[i] + n, buf);
But how to extract the corresponding jth column?
I can easily do it with a looping structure like:
int buf[m];
for(r=0;r<m;r++)
buf[r]=adj[r][j];
but this will increase time complexity keeping in mind that this operation is required for every element of the array. Any better way to do this?
If you decide to write program in C++, then
Stop using plain C-Style arrays. There is No reason whatsoever for C-Style arrays. Do never use them again. Simply stop this.
Stop using raw pointers. For now and ever. Do not use raw pointers
Do not use new. Never
The language C++, which you want to use, does not support VLA (avariable length arrays), Do not use C-Style arrays in the first place and not at all VLA (like int buf[m];
Especially, do not use such constructs, if you do not understand how thew work
In you first row, you are writing
int **adj=new int *[n];
With that you are allocating an array of pointer. Those pointers are not initialized. They point to somewhere random in the memory.
And with
for(r=0;r<m;r++)
for(c=0;c<n;c++)
cin>>adj[r][c];
You are getting user input and write them into random memory, somehwere, undifined, corrupting the heap and causing a crash.
With
int buf[n];
std::copy(adj[i], adj[i] + n, buf);
you copy some random values into buf. It will look like it works. But it is only by accident.
In the future please use std::vector or std array (if you know the dimension at compile time). For 2 dimensional arrays use a vector of vectors.
See the following example:
int main()
{
const size_t numberOfRows = 3;
const size_t numberOfColumns = 4;
std::vector<std::vector<int>> a2d(numberOfRows, std::vector<int>(numberOfColumns));
// Fill a2d with data
for (size_t row = 0; row < a2d.size(); ++row) {
for (size_t col = 0; col < a2d.front().size(); ++col) {
std::cin >> a2d[row][col];
}
}
// Get 2nd row
std::vector<int> row(numberOfColumns);
std::copy(a2d[1].begin(), a2d[1].end(), row.begin());
return 0;
}
But the problem is in extracting the entire row i and entire column j for every such element.
The algorithm you are trying to implement doesn't need to copy and sort the row and the column every time. You can copy and sort each row and each column once, then reuse those for every element. While time consuming, it should be asintotically faster than traversing the rows and columns multiple times to count the greater values.
See e.g. the following implementation (testable HERE).
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
int main()
{
std::vector<std::vector<int>> a {
{3, 5, 1, 2},
{8, 0, -2, 7},
{1, -5, 3, 6},
};
// Make a transposed copy. That's really cache unfriendly
auto a_t = std::vector<std::vector<int>>(a[0].size(), std::vector<int>(a.size()));
for (size_t r = 0; r < a.size(); ++r)
{
for (size_t c = 0; c < a[r].size(); ++c)
{
a_t[c][r] = a[r][c];
}
}
// Sort the rows of a_t (columns of a)
for (auto & row : a_t)
{
std::sort(row.begin(), row.end());
}
auto c = std::vector<std::vector<int>>(a.size(), std::vector<int>(a[0].size()));
for (size_t i = 0; i < c.size(); ++i)
{
// Sort a (copied) row at a time.
auto row_copy(a[i]);
std::sort(row_copy.begin(), row_copy.end());
// The columns have already been copied and sorted,
// now it just takes a couple of binary searches.
for (size_t j = 0; j < c[i].size(); ++j)
{
auto it_r = std::upper_bound(row_copy.cbegin(), row_copy.cend(), a[i][j]);
auto it_c = std::upper_bound(a_t[j].cbegin(), a_t[j].cend(), a[i][j]);
c[i][j] = std::distance(it_r, row_copy.cend())
+ std::distance(it_c, a_t[j].cend());
}
}
for (auto const & row : c)
{
for (auto i : row)
std::cout << std::setw(3) << i;
std::cout << '\n';
}
}

Creating 2-D vector with values from another 2-D vector

I have a 2-D vector called cosmic_ray_events that has a size equal to 898281 and I created another 2-D vector called high-energy_cosmic_rays. I put in a check in cosmic_ray_elements that filters out values that are less than 100 and are located at cosmic_ray_events[i][3]. If the value is greater than 100 then I would like to transfer all the elements associated with cosmic_ray_event[i][j] to another 2-D vector or resize this current 2-D vector so that it only contains vectors that had cosmic_ray_events[i][3] greater than 100. I get a segmentation fault when I try to set cosmic_ray_events[i][j] equal to another 2-D vector. I am not sure how to transfer the elements from one 2-D vector to another without getting a segmentation fault.
vector<vector<double> > high_energy_cosmic_rays(HE_CR, vector<double>(9,0));
for(int i = 0; i < cosmic_ray_events.size(); i++)
{
if(cosmic_ray_events[i][3] >= 100.)
{
for(int j = 0; j < 9; j++)
{
high_energy_cosmic_rays[i][j] = cosmic_ray_events[i][j];
}
}
}

how to refer to a column of a 2D array (matrix) in C++

I have declared a 2D array in the following way (please note that I'm very beginner!)
double **A=new double*[10];
for(int i=0;i<10;i++)
A[i]=new double[5];
So I guess this already defines a matrix of size 10 by 5.
I know that to refer to its row I can use
A[i]
But the question is, how to refer to a column of A? something like A[][i]?
You cannot access a column directly.
You can either access a row by A[i] (which is an array itself) or an element A[i][j] (which is a single double in your case).
If you want to get a column you have to iterate throw the array
for(unsigned int i = 0; i < 10; i++)
{
A[i][2] // do something
}
Accesses the third column.
So it is useful to think about if you want to create a 10x5 or a 5x10 matrix. If you often need to work with just a row or an column, it may be a good idea to invert the array layout (here switch columns and rows)
EDIT:
Here is some simplified explanation:
Imagine the following code
int** A = new int*[2];
for(int i=0;i<2;i++)
A[i]=new int[3];
// more init code
Then the array in memory may look like this:
So it is simple to see that the "blue row" can be accessed directly as you have its startaddress in A[0]
But if you want every third element of the sub arrays you have to iterate through A and add 2 to every startadress. Especially as there is no guaranteed fixed distance in memory between the subarrays if you use heap memory via "new".
But you often can speedup computations by choosing the layout of your arrays in a good way. One could for example store the second matrix transposed when implementing matrix multiplication.
Enother way using pointers.
// Matrix dimentions
int n_rows = 10;
int n_cols = 5;
// create rows as pointers to columns
double **A = new double*[n_rows];
// create columns
for (int i = 0; i < n_rows; i++)
{
A[i] = new double[n_cols];
}
// Fill our matrix
int count=0;
for (int i = 0; i < n_rows; i++)
{
for (int j = 0; j < n_cols; j++)
{
A[i][j]=count;
++count;
}
}
// Create pointers columns
double ***A_t = new double**[n_cols];
// create matrix pointers rows
for (int i = 0; i < n_cols; i++)
{
A_t[i] = new double*[n_rows];
}
// And fill it with pointers to transposed main matrix elements
for (int i = 0; i < n_rows; i++)
{
for (int j = 0; j < n_cols; j++)
{
A_t[j][i]=&A[i][j];
}
}
// output first row/column for each case
for (int i = 0; i < n_cols; i++)
{
cout << *(A[0]+i) << endl;
}
cout << "-------------"<< endl;
for (int i = 0; i < n_rows; i++)
{
cout << **(A_t[0]+i) << endl;
}
// Work with matrices here
// Don't forget to clean everything.
A 2D array looks something like this
if ur 2d array is a[i][j]
then i will be ur rows and j will be ur columns.
if u want to access columns of first row you can do something like this
a[0][1] a[0][2] a[0][3]
see the link it will clear you more.
http://i.stack.imgur.com/21Bqr.png
Rows and columns are sort of abstracted away, you can consider the spatial orientation to go in either direction if you want (10 columns, or 5 columns if you see what I mean). But obviously you need to keep your use consistent.
It probably makes sense to keep the 'outer' array the column, so that A[x][y] makes sense in a cartesian coordinate type sense. From your example, you want to be indexing like A[i][] (i.e. your i index is the column, or X coordinate).
You cannot refer to a column in this way. This is because you dont really have a matrix, you specified an array of arrays. The arrays are your rows, but the columns are not directly stored. If you want to get a whole column, you have to run through all rows, receive the value stored in that column and store it in a different array.
auto column = new double[10];
for(int i = 0; i < 10; i++){
column[i] = A[i][2] //if you want to get the 2nd column
}
Elements of any row can be referred by arr[row_num][i].
Similarly elements of any column can be referred by arr[i][col_num].
Note that indexes are zero-based in C/C++. So if your column/row size is x, i can vary from 0 to x-1.
As you are a beginner, i would also like to tell you a bit more about arrays in C/C++. Firstly, i would suggest you to read about pointers if you are not familiar with them.
When you declare an array, say, int arr[10], arr[0] means the first element. Also, arr + 0 (or simply arr) means the address of the first element. Similarly, arr[i] means ith element, arr + i means address of the ith element. To print the value at an address, in c/c++, you can use value-at operator, represented by (*), e.g. *(arr + i) will be equivalent to arr[i], i.e. the ith element. Also, address of operator (&) gives to the address of an element, &arr[i] is equivalent to (arr + i).
If arr is a 2-d array, arr[i][j] means jth element of ith row. arr[i] means address of first element of ith row. c/c++ are row-major, which means first row is filled first and then second and so on. and we have to specify the row size always while declaring a 2-d array.
Note: In pointer-arithmetic, arr+i, and arr+i+1, etc. are not being incremented by 1, but by the size of the element it is pointing to.
So, to refer to a row, we can do the following:
//note that arr[row_num] is an address
int * new_1d_arr = arr[row_num];
for(int i = 0; i < row_size; i++)
cout << new_1d_arr[i] << endl;
Similarly, we can also refer to an column, but it would be a bit more complex, as we will have to increment i, not by 1, but by the row_size, due to the fact that arrays in c/c++ are row-major, and we would have to skip over number of elements (equal to row_size) to get to the next element in the same column.

How to create a two dimensional array of given size in C++

I need to create a square matrix of a given size. I know how to create a dynamic one-dimensional array of a given size. Doesn't the same work for two dimensinal arrays like the lines below?
cin>>size;
int* a[][]=new int[size][size]
int* a[][]=new int[size][size]
No, this doesn't work.
main.cpp:4: error: only the first dimension of an allocated array may have dynamic size
new int[size][size];
^~~~
If the size of the rows were fixed then you could do:
// allocate an array with `size` rows and 10 columns
int (*array)[10] = new int[size][10];
In C++ you can't have raw arrays with two dimensions where both dimensions are dynamic. This is because raw array indexing works in terms of pointers; for example, in order to access the second row a pointer to the first needs to be incremented by the size of the row. But when the size of a row is dynamic the array doesn't know that size and so C++ doesn't know how to figure out how to do the pointer increment.
If you want an array with multiple dynamic dimensions, then you need to either structure the array allocations such that C++'s default array indexing logic can handle it (such as the top answers to this duplicate question), or you need to implement the logic for figuring out the appropriate pointer increments yourself.
For an array where each row has the same size I would recommend against using multiple allocations such as those answers suggest, or using a vector of vectors. Using a vector of vectors addresses the difficulty and dangerousness of doing the allocations by hand, but it still uses more memory than necessary and doesn't allow faster memory access patterns.
A different approach, flattening the multi-dimensional array, can make for code as easy to read and write as any other approach, doesn't use extra memory, and can perform much, much better.
A flattened array means you use just a single dimentional array that has the same number of elements as your desired 2D array, and you perform arithmetic for converting between the multi-dimensional indices and the corresponding single dimensional index. With new it looks like:
int *arr = new int[row_count * column_count];
Row i, column j in the 2d array corresponds to arr[column_count*i + j]. arr[n] corresponds to the element at row n/column_count and column n% column_count. For example, in an array with 10 columns, row 0 column 0 corresponds to arr[0]; row 0, column 1 correponds to arr[1]; row 1 column 0 correponds to arr[10]; row 1, column 1 corresponds to arr[11].
You should avoid doing manual memory management using raw new and delete, such as in the case of int *arr = new int[size];. Instead resource management should be wrapped up inside a RAII class. One example of a RAII class for managing dynamically allocated memory is std::vector.
std::vector<int> arr(row_count * column_count);
arr[column_count*i + j]
You can further wrap the logic for computing indices up in another class:
#include <vector>
class Array2d {
std::vector<int> arr;
int columns;
public:
Array2d(int rows, int columns)
: arr(rows * columns)
, columns(columns)
{}
struct Array2dindex { int row; int column; };
int &operator[] (Array2dindex i) {
return arr[columns*i.row + i.column];
}
};
#include <iostream>
int main() {
int size;
std::cin >> size;
Array2d arr(size, size);
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
arr[{i, j}] = 100;
}
}
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
std::cout << arr[{i, j}] << ' ';
}
std::cout << '\n';
}
}
If you're using C++11 you can also use std::array.
const int iRows = 3, iCols = 3; // number of rows and columns
std::array<std::array<int, iCols>, iRows> matrix;
// fill with 1,2,3 4,5,6 7,8,9
for(int i=0;i<iRows;++i)
for(int j=0;j<iCols;++j)
matrix[i][j] = i * iCols + j + 1;
This class also allows for bounds checking by using the function
std::array::at
which (just like operator[]) returns a const reference if the array-object is const-qualified or a reference if it is not. Please note that
std::array
is not a variable-sized array-type, like
std::vector
You can use std::vector:
std::vector<std::vector<int*>> a(size, std::vector<int*>(size));
This will create a dynamically allocated 2D array of int* with width and height equal to size.
Or the same with new:
int*** a = new int**[size];
for (size_t i = 0; i < size; ++i)
a[i] = new int*[size];
...
for (size_t i = 0; i < size; ++i)
delete a[i];
delete a;
Note that there's no new[][] operator in C++, you just have to call new[] twice.
However, if you want to do it with new and delete instead of std::vector, you should use smart pointers instead of raw pointers, for example:
std::unique_ptr<std::unique_ptr<int*>[]> a(new std::unique_ptr<int*>[size]);
for (size_t i = 0; i < size; ++i)
a[i].reset(new int*[size]);
...
// No need to call `delete`, std::unique_ptr does it automatically.

Creating a two-dimensional vector from a file?

I'm trying to read data from a grid, in a 20x20 file. I'm using a two-dimensional vector of vectors of strings.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
#define HEIGHT 20
#define WIDTH 20
typedef vector<vector<string> > stringGrid;
bool readGrid(stringGrid& grid, string filename) {
grid.resize(HEIGHT);
for (int i = 0; i < HEIGHT; i++)
grid[i].resize(WIDTH);
ifstream file;
string line;
file.open(filename.c_str());
if (!file.is_open()) {
return false;
}
for (int i = 0; i < HEIGHT; i++)
{
while (getline(file, line)) {
grid[i].push_back(line);
}
}
return true;
}
void displayGrid(stringGrid grid)
{
for (int row = 0; row < HEIGHT; row++)
{
for (int col = 0; col < WIDTH; col++)
{
cout << grid[col][row];
}
cout << endl;
}
}
int main(){
stringGrid grid;
readGrid(grid, "test.txt");
displayGrid(grid);
return 0;
}
However, when I run this code, the program only outputs a few blank lines.
Why doesn't this code work? The logic seems sound enough.
You can do what Kocik said or you could use vector::reserve instead of vector::resize in your code. It should then work.
reserve simply reserves enough memory to avoid reallocating memory while it's pushing back items.
resize actually resizes the vector by adding n default items. In your case, those items are empty vectors of strings, so you'll get 20 of them in your vector before any other items you subsequently push back.
Here is a bit more info about the difference between the two methods.
You use grid[i].push_back(line); after you created 20 elements with grid[i].resize(WIDTH);. Method push_back add new element on the end of the vector, so new elements will have index 21, 22 .. 40.
You have two options:
you can set new values to initialized elements with some iterator, or
you can just skip resize and push new elements to empty vector. Simply delete those two lines:
for (int i = 0; i < HEIGHT; i++)
grid[i].resize(WIDTH);</li>
As an aside, it's generally considered bad practice to use a vector-of-vectors. Instead, use a class that wraps a single vector and does index arithmetic (either x*h+y or y*w+x depending on which major order you want).