int matrix[9][9],*p;
p=matrix[0];
this works and gives first row of matrix, but how to get first column of matrix I've tried p=matrix[][0]; ? Also I don't understand why below code gets compiler error ?
int matrix[9][9],p[9]; // it looks really ugly, byt why it doesn't work ?
p=matrix[0]; // compiler gives "invalid array assigment"
is it because multidimensional arrays are arrays of arrays - and we should interpret matrix[i][j] as j-th element of i-th nested array ?
In C/C++, multidimensional arrays are actually stored as one dimensional arrays (in the memory). Your 2D matrix is stored as a one dimensional array with row-first ordering. That is why getting a column out of it is not easy, and not provided by default. There is no contiguous array in the memory that you can get a pointer to which represents a column of a multidimensional array. See below:
When you do p=matrix[0], you are just getting the pointer to the first element matrix[0][0], and that makes you think that you got the pointer to first row. Actually, it is a pointer to the entire contiguous array that holds matrix, as follows:
matrix[0][0]
matrix[0][1]
matrix[0][2]
.
.
matrix[1][0]
matrix[1][1]
matrix[1][2]
.
.
matrix[8][0]
matrix[8][1]
matrix[8][2]
.
.
matrix[8][8]
As seen above, the elements of any given column are separated by other elements in the corresponding rows.
So, as a side note, with pointer p, you can walk through the entire 81 elements of your matrix if you wanted to.
You can get the first column using a loop like
for(int i = 0; i < 9; i++)
{
printf("Element %d: %d", i, matrix[i][0]);
}
I think the assignment doesn't work properly because you're trying to assign something's that's not an address to a pointer.
(Sorry this is c code)
There is no difference between specifying matrix[81] or matrix[9][9]
matrix[r][c] simply means the same as matrix[9*r+c]
There are other containers better suited fort multidimensional arrays like boost::multi_array
http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/index.html
Think of the bare array just like allocating a contiguous piece of memory. You, the programmer then has to handle this piece of memory yourself. The bare name of the array, e.g. matrix is a pointer to the first element of this allocated piece of memory. Then *(matrix+1) is the same as matrix[0][1] or matrix[1].
p is an array of int, matrix[0] is a pointer..
matrix itself is the nearest thing you can get to a column of the array, inasmuch as (matrix + 1)[0][0] is the same as matrix[1][0].
Here's a program which builds a 10x10 array and prints the second column:
#include <iostream>
using namespace std;
int main()
{
int aa[10][10];
for(int i = 0; i<10; i++)
for(int j = 0; j<10; j++)
aa[i][j] = i*10+j;
int col = 2;
// pointer to a length-10 1d array
int (*p)[10] = (int (*)[10])&(aa[0][col]);
for(int i =0; i<10; i++)
cout << *(p[i]) << endl;
return 0;
}
The difference from aa[row][2] is using a pointer to a length-10 1d int array int (*p)[10], For more context about int (*p)[10], see this answer
p saves the address of 1d array {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
. And p+1 saves the address of 1d array {12, 13, 14, 15, 16, 17, 18, 19, 20, 21}. *(p[1]) or *(*(p+1)) access the first value of 1d array.
If you want your matrix to contiguous locations, declare it as a one dimensional array and perform the row and column calculations yourself:
int contiguous_matrix[81];
int& location(int row, int column)
{
return contiguous_matrix[row * 9 + column];
}
You can also iterate over each column of a row:
typedef void (*Function_Pointer)(int&);
void Column_Iteration(Function_Pointer p_func, int row)
{
row = row * MAXIMUM_COLUMNS;
for (unsigned int column = 0; column < 9; ++column)
{
p_func(contiguous_matrix[row + column]);
}
}
For static declared arrays you can access them like continuous 1D array, p = matrix[0] will give you the 1st column of 1st row. Then the 1D array can be accessed like p[i], *(p+i), or p[current_raw * raw_size + current_column).
The things are getting tricky if a 2D array is represented with **p as it will be interpreted as an array of pointers to 1D arrays.
I don't know if this is a efficient solution but by doing this way I'm able to get the column,
int arr[9][2] = { {2, 57}, {3, 66}, {4, 73}, {5, 76}, {6, 79}, {7, 81}, {8, 90}, {9, 96}, {10, 100}};
int c[18];
int co = 0;
for (auto & i : arr) {
for (int j : i) {
c[co++] = j;
}
}
for (int i = 0; i < co; ++i) {
if (i % 2 != 0)
std::cout << c[i] << " ";
}
Related
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';
}
}
Apperantly this code works
void printD(int * ar,int r)
{
for(int i = 0; i < r; i++)
cout<<ar[i]<<endl;
}
int main()
{
int ar[3] = {1,2,3};
printD(ar,3);
return 0;
}
But this code does not work
void print2D(int ** ar,int r,int c)
{
for( int i = 0; i< r;i++)
for(int j = 0; j < c;j++)
cout<<ar[i][j]<<endl;
}
int main()
{
int ar2[1][2] = {{3,1}};
print2D(ar2,1,2);
return 0;
}
I do not understand why this does not work?
The problem lies within how the memory addresses are calculated. a[0] is the first element, and a[1] is the second element, so the address of a[1] is the position of a[0] plus the size of the element. No problem here, the address of any element can be calculated with the position of the first element multiplied with the offset times the element size.
How does this work with multi-dimensional arrays? What's the distance between a[0][5] and a[1][5]? Well, that depends on the row size (I'm using this terminology for the sake of this example, in reality, there aren't any "rows"), since in the end it's just one block of memory. If a row has 10 elements, then the distance is 10 times the size of an element. So this row size is important, the exact location of the elements in the array can't be calculated without it. Now with this here:
void print2D(int ** ar,int r,int c)
How could it know that row size? ar[1][0] is the first element of the second row, so if a row had size 10, then that would be the 10th element in the memory block. However, if the row size is 20, then it would be the 20th element, and that would be a different address. So how would it know?
The code doesn't work because it would require information to calculate the addresses, but it doesn't have that information.
This array int ar2[1][2] actually decays to int(*)[2].
There is no intermediate pointer to pointer that gets allocated, there is a contiguous 1D array that has can be accessed in 2D, hence the remaining [2] that gives the stride to go from one row to another.
A 2-dimensional array is implicitly converted to a pointer to a 1D array, not to a pointer to a pointer.
void print2D(int (*ar)[2],int r,int c)
{
// definition omitted for brevity
}
int main()
{
int ar2[1][2] = {{3,1}};
print2D(ar2,1,2);
return 0;
}
There is also no conversion from a pointer to an array (as in the above sample) into a pointer to pointer.
For more dimensions, this also works - except that all dimensions other than the first must be known at compile time.
I have this function:
void reverse(int* nums, unsigned int size)
This function is supposed to reverse the values in the array it is getting.
Now for reversing I thought to create another array with the size of the array passed in. Assigning this new one from the end of the original array to the start.
But I am a kind of new in C++, So I don't know how to create dynamic array in the size of the parameter of the function.
It's actually not necessary to allocate a new array here. See if you can find a way to solve this problem just by rearranging the existing elements in-place.
Given that this seems like it's an exercise with pointers, you can allocate space by using the new[] operator:
int* auxiliaryArray = new int[size];
You'd then free it by writing
delete[] auxiliaryArray;
However, this isn't the preferred way of doing this in C++. The better route is to use std::vector, which does all its own memory management. That would look like this:
std::vector<int> auxSpace(size);
You can then access elements using the square brackets as you could in a real array. To do this, you'll need to #include <vector> at the top of your program.
In C++, the recommended way to create an array of variable size would be to use an std::vector
#include <vector>
void reverse(int* nums, unsigned int size)
{
std::vector<int> V(size);
...
}
But that approach isn't the best here for performance because it requires additional memory to be allocated of the size of the array, which could be big. It would be better to start from the outside of the array and swap members one by one that are at mirroring positions (so if the size is 5, swap 0 and 4, then swap 1 and 3 and leave 2 alone). This only requires temporary storage of a single int.
You can do it without the need to create another array:
void reverse(int* array, const int size){
for(int i = 0; i < size / 2; i++){
int tmp = array[i];
array[i] = array[size - 1 - i];
array[size - 1 - i] = tmp;
}
}
int main(){
int array[] = {1, 3, 5, 7, 9, 11};
const int size = sizeof(array) / sizeof(array[0]);
reverse(array, size);
for(int i(0); i < size; i++)
std::cout << array[i] << ", ";
}
As you can see above in the loop you only need to swap the first element (element 0) with the n-1 element and the second one with n-1-1 and son on...
Remember arrays are indexed from 0 through n-1.
If you want to allocate new array which is not practical:
int* reverse2(int* array, const int size){
int* tmp = new int[size];
for(int i(size - 1), j(0); j < size; j++, i--)
tmp[j] = array[i];
return tmp;
}
int main(){
int array[] = {1, 3, 5, 7, 9, 11};
for(int i(0); i < size; i++)
std::cout << array[i] << ", ";
std::cout << std::endl;
int* newArray = reverse2(array, size);
for(int i(0) ; i < size; i++)
std::cout << newArray[i] << ", ";
std::cout << std::endl;
delete[] newArray;
return 0;
}
If you want to use a new array you can, but I think is to kill flies with a cannon.
Looks like you are using plain C code and not C++. I say that because of the signature of the function. The signature of the function in a common C++ code could be something like this other:
void reverse(std::vector& items);
You can reverse the current array without a new array, using the current one. You are passing the pointer to the first item of the array, and the content is not constant so that you can modify it. A better signature for the function could be:
void reverse(int* const nums, const unsigned int size);
Looks like a pointer problem. Think about the boundaries to iterate the positions of the array. Would you need to iterate the whole array? Maybe only half array? ;)
As bonus track, what about to exchange the values without an auxiliar variable? (this is true into this case that we are using the fundamental type int... remember the binary arithmetic).
array[pos_head] ^= array[pos_tail];
array[pos_tail] ^= array[pos_head];
array[pos_head] ^= array[pos_tail];
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.
For example: int a[4] = {2, 4, 34}
Lets say the address of a[0] is at 2000 and we know the value of the element at a[0] is 2.
Given only a memory address and a value of an element, is it possible to determine the position of the element in the array?
If so, please provide an example on how to do this.
Is this what you are looking for? Just using some pointer arithmetic;
int main ()
{
int ary[] = { 1, 2, 3, 5 };
int * address_of_2 = &ary[ 1 ];
int index_of_2 = address_of_2 - ary;
return 0;
}
The memory location will be unique for each element in the array. So yes, if you know the memory location, you can iterate through the array and simply find when the reference equals your value.
for (int i=0; i < arr_size; i++) {
if (&arr[i] == address && arr[i] == *address) {
cout << i << endl;
break;
}
}
If given an array, the size of the array and type of element(i.e. integer), than yes, given also the address of an element and the value, you could sort through the array and find its position. Note the significance that the array block is contiguous.
array = array;
n = sizeof(array)/sizeof(*array);
oAddress = array;
fAddress = array + n * sizeof(*array);
locOfElement = (elementAddress - oAddress) / (fAddress - oAddress) * n;