Which to print first in a 2D Array? - arrays

I was told that there was a convention when you have a code to print an array, that there is a value that must come first than the other one, for example:
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; column++)
System.out.print("" + array[i][j]);}
Would be i first or it needs to be j first? I find answers like this one but they don't solve my doubt...
PS: I'm not asking just about Java, but about C#, C, C++, Javascript, etc.

The convention is to do it in order, as you have written:
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; column++)
System.out.print("" + array[i][j]);}
Here, i is before j in the loops, and array is indexed by i before j as well.
This is the natural order, as written in the code. It is also the order in which the memory elements are stored in most languages (Java, C#, C, C++). This is called row-major order, where elements in the same row are in contiguous memory locations.
For a 3 by 3 array a[3][3] in row-major order, the elements are stored as:
a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2]
Indexing into the array in row-major order also has performance benefits. By accessing memory sequentially, you minimise cache misses.

for (int i = 0; i < array.length; i++) {
means that i serves as an index for the elements of array (the elements happen to be sub arrays).
for (int j = 0; j < array[i].length; column++)
indicates that j serves as an index for the elements of array[i] (the sub arrays of array).
So yes, i needs to be before j.

Related

Which method for accessing a 2D array in C is most effective? (Using Pointers)

If you have a function that takes the pointer of an array, would there be any use in using pointers to each element in the array, or is it redundant? For example:
int sum(int(*arr)[3]) {
int i,j, sum = 0;
for (i =0; i < ROW ; i ++) {
for (j =0; j < COL ; j ++) {
sum = sum + *(*( arr +i )+j);
}
}
}
Would using arr[i][j] be the same in this case?
arr[i] is required by the standard to be equivalent to *(arr + i) so no, there is no point in not using arr[i] which is more readable.
Speeding up 2d array access is a complex topic. There are some techniques for performance improvement, but those take hardware architecture (e.g. cache) into account are are related to access patterns rather than access syntax.

C++ Array unknown operation

Im reading over some code on github trying to understand what its doing.
I came across this:
for (int k = 0; k < N/GROUP_SIZE; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < GROUP_SIZE; j++) {
tempB[i][j] = *(B+k*GROUP_SIZE+i*N+j);
}
}
B is a one dimensional array of size (N*N)
tempB is a two dimensional array of size [N][GROUP_SIZE]
Im quite unsure what this line does though:
tempB[i][j] = *(B+k*GROUP_SIZE+i*B_WIDTH+j);
Does it access only part of the array?
I would try to google this question, but im not sure what to call the operation
temp[i][j] = accesses one cell of a multi-dimensional array and places the value into it.
As for *(B+k*GROUP_SIZE+i*B_WIDTH+j), here B is the name of an array, which is also a pointer to the first element of that array.
*(B + a) is equivalent to B[a]. B + 1 would point to the second element of that array, and B + 2 to the second element. * operator dereferences the pointer, and returning value at that index.

Dependency in Adjacent Elements while Updating 2d array (OpenMP)

I have a 2d array, say arr[SIZE][SIZE], which is updated in two for loops in the form:
for(int i = 0; i < SIZE; i++)
for(int j = 0; j < SIZE; j++)
arr[i][j] = new_value();
that I am trying to parallelise using OpenMP.
There are two instances where this occurs, the first is the function new_value_1() which relies on arr[i+1][j] and arr[i][j+1] (the "edge of the array" issue is already taken care of), which I can happily parallelise using the chessboard technique:
for(int l = 0; l < 2; l++)
#pragma omp parallel for private(i, j)
for(int i = 0; i < SIZE; i++)
for(int j = (i + l) % 2; j < SIZE; j += 2)
arr[i][j] = new_value_1();
The issue comes with this second instance, new_value_2(), which relies upon:
arr[i+1][j],
arr[i-1][j],
arr[i][j+1],
arr[i][j-1]
i.e. the adjacent elements in all directions.
Here, there is a dependency on the negative adjacent elements, so arr[0][2] = new_value_2() depends on the already updated value of arr[0][1] which would not be computed until the second l loop.
I was wondering if there was something I was missing in parallelising this way or if the issue is inherent with the way the algorithm works? If the former, any other approaches would be appreciated.
I was wondering if there was something I was missing in parallelising this way or if the issue is inherent with the way the algorithm works?
Yes, you're missing something, but not along the lines you probably hoped. Supposing that the idea is that the parallel version should compute the same result as the serial version, the checkerboard approach does not solve the problem even for the new_value_1() case. Consider this layout of array elements:
xoxoxo
oxoxox
xoxoxo
oxoxox
On the first of the two checkerboard passes, the 'x' elements are updated according to the original values of the 'o' elements -- so far, so good -- but on the second pass, the 'o' elements are updated based on the new values of the 'x' elements. The data dependency is broken, yes, but the overall computation is not the same. Of course, the same applies even more so to the new_value_2() computation. The checkerboarding doesn't really help you.
If the former, any other approaches would be appreciated.
You could do the computation in shells. For example, consider this labeling of the array elements:
0123
1234
2345
3456
All the elements with the same label can be computed in parallel (for both new_value() functions), provided that all those with numerically lesser labels are computed first. That might look something like this:
for(int l = 0; l < (2 * SIZE - 1); l++) {
int iterations = (l < SIZE) ? (l + 1) : (2 * SIZE - (l + l));
int i = (l < SIZE) ? l : (SIZE - 1);
int j = (l < SIZE) ? 0 : (1 + l - SIZE);
#pragma omp parallel for private(i, j, m)
for(int m = 0; m < iterations; m++) {
arr[i--][j++] = new_value_1();
}
}
You won't that way get as much of a benefit from parallelization, but that is an inherent aspect of the way the serial computation works, at least for the new_value_2() case.
For the new_value_1() case, though, you might do a little better by going row by row:
for(int i = 0; i < SIZE; i++)
#pragma omp parallel for private(j)
for(int j = 0; j < SIZE; j++)
arr[i][j] = new_value_1();
Alternatively, for the new_value_1() case only, you could potentially get a good speedup by storing the results in a separate array:
#pragma omp parallel for private(i, j), collapse(2)
for(int i = 0; i < SIZE; i++)
for(int j = 0; j < SIZE; j++)
arr2[i][j] = new_value_1();
If that requires you to copy the result back to the original array afterward then it might well not be worth it, but you could potentially avoid that by flipping back and forth between two arrays: compute from the first into the second, and then the next time around, compute from the second into the first ( if the problem [PSPACE] scaling permits having such an extended in-RAM allocation, i.e. it again comes at a [PTIME] cost, hopefully paid just once ).

Understanding two dimensional arrays

Here's the code and wondering if you can help me understand it.
/* Two dimensional array */
#include <stdio.h>
void main() {
int i, j, sum[2], mean[2];
int mark[3][2] = { { 34, 56}, { 48, 65}, { 53, 59} };
for (j = 0; j < 2; j++)
sum[j] = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
for (j = 0; j < 2; j++)
mean[j] = sum[j] / 3;
printf("Average mark in Mathematics is %d\n", mean[0]);
printf("Average mark in Chemistry is %d\n", mean[1]);
}
My understanding of it so far....
Define data types i, j, sum[2], mean[2] as integers.
Initialising the array....mark is data type int, the array should have 3 rows and 2 columns.
First for loop, j initialised at 0, condition: j has to be less than 2, update: add one onto the value of j. Sum of j = 0.
Also for 2nd loop, i initialised at 0, condition: i has to be less than 3, update: add one onto the value of i.
Similar for the next line that uses the for loop and value j.
I'm a bit confused about the syntax:
sum[j] = sum[j] + mark[i] [j]; does this mean, work out the sum of j and add it to the marks contained in the array displayed as [i] and [j].
After this is completed then similar j loop though not sure how this interacts with the previous loops.
Mean calculated and values printed to the screen.
When I've looked at the worked example...
sum[0] = 0 and sum[1] = 0, I don't really understand why sum[1] is also 0.
Firstly, i=0 and j=0,
sum[0] = sum[0] + mark [0,0]
then j=1
sum[1]=sum[1]+mark[0,1]
then
i=1, j=0
sum[0] = sum[0] + mark [1,0]
then
sum[1] = sum[1]+mark[1,1]
then i = 2, j=0
sum [0] = sum[0]+ mark[2,0]
then
sum[1] = sum[1]+ mark[2,1]
What is confusing me a bit is how the loops are interacting with each other and the values of i and j throughout.
I know that the 2d array would be in a table (that I can't seem to format here).
Would appreciate if anyone could shed some light on this.
sum[j] = sum[j] + mark[i][j]; can be simplified as sum[j] += mark[i][j];. It adds the contents of the cell at row i, column j of the 2D matrix mark to the jth element of array sum.
Accessing an element of a 2D array is written mark[i][j] in C, not mark[i, j].
Note that mark[i, j] is not a syntax error: the expression i, j is a comma expression, evaluating i, then discarding it and evaluating j. It is therefore the same as mark[j] which is not a matrix cell but a reference to the jth row of the 2D matrix.
Nope, an array is in fact a pointer (aka an address). When you define int sum[2], sum is the address of the first element of your array of two integer.
So sum is an int* or int[] (same).
Mark is an 2d array. Mark is in fact an array of array. So Mark contain addresses, and thoses addresses are the beggining of some arrays.
(In fact it can be different in the memory, but the compiler do the work).
Mark is a int**, or an address of address of int.
When you do:
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
It's like if you were saying
for each line i in the array, I want to do:
for each value j in the line, I want to do:
...;
Like this, you work on every "line" (or column, visualize the way you want), and for every "line", you work on every value.

C: pointers to arrays, and destructive sorting

I wrote a brief piece of code. It has two functions: bubbleSort is a bubble sorting function (smallest to largest), and "int main" is used to test this piece of code with an int array of size 5.
I'd like this to destructively sort the array, and not simply pass through a copy. I have looked and looked, but I am still not entirely clear how this should work. What am I missing here?
#include <stdio.h>
void bubbleSort(int values[], int n);
int main(void) {
//set simple test array to make sure bubbleSort works
int arr[5] = {5,4,3,2,1};
//run it through function, and then print the now sorted array to make sure
bubbleSort(arr, 5);
printf("%i", arr);
return 0;
}
void bubbleSort(int values[], int n)
{
for (int i = 0; i < n; i++) {
for (int j = 0, hold = 0; j < n-i; j++) {
if (values[j] > values[j+1]) {
hold = values[j+1];
values[j+1] = values[j];
values[j] = hold;
}
}
}
return;
}
Note: The rest of my code looks sound to my amateur coding mind, but please give me pointers on what i can improve, what can be better, etc. I thought about using recursion for the bubble sort but i'm not yet as comfortable with C as I'd like to be to implement that. However if you have suggestions i'll be more than happy to read them.
thanks!
Looks like your function is sorting the array (although with some bugs) and you are just printing the result incorrectly. printf doesn't know how to print arrays. Instead, you need to use a loop to print each integer one at a time:
for(int i=0; i<5; i++){
printf("%d ", arr[i]);
}
printf("\n");
After changing this, the output is 1 2 3 4 5, as expected.
However, as mentioned in the comments, there are some bugs in the implementation of the bubblesort. For example, it tries to read elements from indedex after the end of the array, which is undefined behavior (namely, j+1 can be 5, which is out of bounds). I would recommend checking your book again to get a correct implementation of bubblesort.
There is one issue in you bubble sort code which must be fixed. Your inner loop has the issue:
/* for (int j = 0, hold = 0; j < n-i; j++) { */ // ISSUE here
for (int j = 0, hold = 0; j < n-i-1; j++) { // j < n-i-1 should be the condition
This is becasue, take the case of when i = 0, i.e. the first iterartion of outer for loop. This time, j < n - i will be true when j is one less than n - which is the last index of your array. Then you do comaprision between values[j] and values[j+1], where values[j+1] is clearly out of bound of your array. This will invoke undefined behavior, and your function will not give deterministic results.
Next improvement could be that your outer loop only needs to iterate from i = 0 till i < n-1, i.e. one times less than the total elements. You are interating one time more than needed.
Third, you can use a flag to keep track of weather you swap at least once in your inner loop. If there there are no swaps in inner loop then it means that array is already sorted. So at the end of each iteration of inner loop you can see if any swap was done, and if no swaps were done then break out of the outer loop. This will improve performance in cases where array is already almost sorted.
void bubbleSort(int values[], int n)
{
int swap; // To use as a flag
// for (int i = 0; i < n; i++) {
for (int i = 0; i < n-1; i++) {
swap = 0; // set swap flag to zero
// for (int j = 0, hold = 0; j < n-i; j++) {
for (int j = 0, hold = 0; j < n-i-1; j++) {
if (values[j] > values[j+1]) {
hold = values[j+1];
values[j+1] = values[j];
values[j] = hold;
swap = 1; // swap was done
}
}
if (swap == 0) // If no swap was done
break; // Means array already sorted
}
return;
}
And, although not related to your sorting function, as others have pointed out, printf("%i", arr); is wrong, and will invoke undefined behavior because you are using a wrong format specifier in printf. It seems like you are trying to print the array. For that you can do:
// printf("%i", arr);
for (int i = 0; i < 5; i++)
printf("%d ", arr[i];)
printf("\n");
Your code already sorts the array in-place - although there is a bug in it. I'll address the subject of the question only (in-place sorting of an array in C) as comments have already highlighted the bugs with the sort function.
The print-out of the result is incorrect though as it tries to print the arr pointer as an integer:
sort.c:10:18: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%i", arr);
~~ ^~~
1 warning generated.
However changing this to:
for (int i = 0; i < 5; i++)
printf("%i", arr[i]);
fixes the problem with the output.
Perhaps your confusion comes from how arrays are actually a syntactic way to access pointers in C. arr is a pointer. arr[1] is the same as *(arr + 1) (the contents of the pointer arr + 1 using pointer arithmetic, which increments the pointer by the sizeof the type). So when you pass arr into the function, you are passing a pointer to the existing array, then you are modifying its contents, sorting the array in-place.

Resources