Reversing and printing out the contents of an array using recursion - c++

I need to reverse and print out the contents of the following array using recursion:
int myArray[] = { 65, 89, 74, 25, 21, 54, 38, 64, 11, 45, 19, 48, 46, 83 };
The call to the function is:
printArray(myArray, arraySize, 0, arraySize - 1);
And my function is:
void printArray(int values[], int sizeOfArray, int low, int high) {
if (low < high) {
int tempValue = values[low];
values[low] = values[high];
values[high] = tempValue;
printArray(values,sizeOfArray, low+1 ,high-1);
}
for (int i = 0; i < sizeOfArray; i++) {
cout << values[i]<<' ';
}
}
The output that I am getting is the reversed array a total of 8 times.
83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65 83 46 48 19 45 11 64 38 54 21 25 74 89 65
I can not seem to figure out what is wrong here. I am also new to arrays and recursion so any help is greatly appreciated.

If the same function is supposed reverse, then print, the sequence, you can do it by surrounding your for-loop with a condition that is only true on the outer-most invoke of the recursive call stack.
void printArray(int values[], int sizeOfArray, int low, int high)
{
if (low < high)
{
int tempValue = values[low];
values[low] = values[high];
values[high] = tempValue;
printArray(values, sizeOfArray, low+1 ,high-1);
}
if (low == 0)
{
for (int i = 0; i < sizeOfArray; i++)
std::cout << values[i]<<' ';
std::cout << '\n';
}
}
Worth noting. sizeofArray, or high, are pointless in this code. You don't need both. You can just as easily do this, for example:
void printArray(int values[], int low, int high)
{
if (low < high)
{
int tempValue = values[low];
values[low] = values[high];
values[high] = tempValue;
printArray(values, low+1 ,high-1);
}
if (low == 0)
{
for (int i = 0; i <= high; i++)
std::cout << values[i]<<' ';
std::cout << '\n';
}
}
Or
Likewise, you can use a template to do this to gather the native array size at compile time (which I leave as a future exercise, as right now it would probably be more a Rube Goldberg solution to you than anything else).

Related

How did changing datatype of an array from int to long long and INT_MAX to LLONG_MAX in a C++ code result in a runtime error?

The values in my input testcase files were such that at some point in the code, values would exceed the capacity of int, so I figured I'd change the datatype of this particular array holding this value greater than INT_MAX from int to long long and change maximum values in the code to LLONG_MAX from INT_MAX so that comparisons during runtime don't yield a wrong answer.
However, now the code seems to get stuck with a runtime error even before arriving at the mentioned testcase. It now fails at a case that it used to pass when the values were all int oriented. I don't understand how this is possible.
The testcase which passes with int but fails with ll is:
100 50
1 23 133
1 87 16
2 9 78
3 12 117
3 39 19
5 25 219
5 47 130
5 97 157
6 50 114
9 11 25
9 39 227
10 45 187
10 77 120
12 19 85
13 43 247
14 16 4
15 33 223
16 33 1
19 69 204
20 35 119
20 43 213
20 86 19
22 40 233
23 33 61
23 79 152
26 89 213
27 57 129
28 42 220
31 68 84
31 69 183
32 39 145
32 100 117
33 49 198
34 48 78
37 66 200
37 91 77
39 44 235
41 70 109
42 92 33
44 74 196
48 73 26
51 57 216
53 70 158
63 98 220
66 72 148
80 93 150
81 99 54
83 84 129
83 89 177
95 100 16
Below is the code that gives an error at this tc.
#include<bits/stdc++.h>
using namespace std;
# define ll long long int
ll update, previous;
set<pair<ll, int>> dist;
auto it=dist.begin();
int ind=0, n, i, j;
pair<ll, int>p;
void dij(vector<pair<int, ll>> tree[], bool decided[], ll d[], int path[]) {
ind=0;
while(!dist.empty()) {
it=dist.begin();
if(it==dist.end()) return;
ind=it->second;
dist.erase(it);
decided[ind]=1;
for(j=0; j<tree[ind].size(); j++) {
update=d[ind]+tree[ind][j].second;
previous=d[tree[ind][j].first];
if(update<previous) {
p=make_pair(previous, tree[ind][j].first);
dist.erase(dist.find(p));
p=make_pair(update, tree[ind][j].first);
dist.insert(p);
path[tree[ind][j].first]=ind;
}
d[tree[ind][j].first]=min(update, previous);
}
}
}
int main()
{
ll edges;
ll x, y, weight;
cin>>n>>edges;
vector<pair<int, ll>> graph[n];
for(i=0; i<edges; i++) {
cin>>x>>y>>weight;
x--; y--;
graph[x].push_back({y, weight});
graph[y].push_back({x, weight});
}
int src=1;
src--;
ll d[n];
for(i=0; i<n; i++) {
if(src==i) {
dist.insert({0, i});
d[i]=0;
}
else {
dist.insert({LLONG_MAX, i});
d[i]=LLONG_MAX;
}
}
bool decided[n]={0};
int path[n]={-1};
for(int i=1; i<n; i++) path[i]=-2;
dij(graph, decided, d, path);
if(path[n-1]==-2) cout<<-1;
else {
vector<int> s;
int final=n-1;
while (final!=-1) {
s.push_back(final);
final=path[final];
}
reverse(s.begin(), s.end());
for(auto pi:s) cout<<pi+1<<" ";
}
cout<<endl;
}
Below is the code that produces a correct output for this tc.
#include<bits/stdc++.h>
using namespace std;
# define ll long long int
ll update, previous;
set<pair<ll, int>> dist;
auto it=dist.begin();
int ind=0, n, i, j;
pair<ll, int>p;
void dij(vector<pair<int, ll>> tree[], bool decided[], int d[], int path[]) {
ind=0;
while(!dist.empty()) {
it=dist.begin();
if(it==dist.end()) return;
ind=it->second;
dist.erase(it);
decided[ind]=1;
for(j=0; j<tree[ind].size(); j++) {
update=d[ind]+tree[ind][j].second;
previous=d[tree[ind][j].first];
if(update<previous) {
p=make_pair(previous, tree[ind][j].first);
dist.erase(dist.find(p));
p=make_pair(update, tree[ind][j].first);
dist.insert(p);
path[tree[ind][j].first]=ind;
}
d[tree[ind][j].first]=min(update, previous);
}
}
}
int main()
{
ll edges;
ll x, y, weight;
cin>>n>>edges;
vector<pair<int, ll>> graph[n];
for(i=0; i<edges; i++) {
cin>>x>>y>>weight;
x--; y--;
graph[x].push_back({y, weight});
graph[y].push_back({x, weight});
}
int src=1;
src--;
int d[n];
for(i=0; i<n; i++) {
if(src==i) {
dist.insert({0, i});
d[i]=0;
}
else {
dist.insert({INT_MAX, i});
d[i]=INT_MAX;
}
}
bool decided[n]={0};
int path[n]={-1};
for(int i=1; i<n; i++) path[i]=-2;
dij(graph, decided, d, path);
if(path[n-1]==-2) cout<<-1;
else {
vector<int> s;
int final=n-1;
while (final!=-1) {
s.push_back(final);
final=path[final];
}
reverse(s.begin(), s.end());
for(auto pi:s) cout<<pi+1<<" ";
}
cout<<endl;
}
The only difference in the 2 codes are the following lines:
void dij(vector<pair<int, ll>> tree[], bool decided[], ll d[], int path[])
void dij(vector<pair<int, ll>> tree[], bool decided[], int d[], int path[])
ll d[n];
int d[n];
dist.insert({LLONG_MAX, i})
dist.insert({INT_MAX, i})
d[i]=LLONG_MAX
d[i]=INT_MAX
Could someone please point out how is this creating the following error which I read is related to "allocating memory where I should not" or "attempting to execute delete with a pointer value that was not obtained from new". What is causing this problem and how should I resolve it?
free(): invalid pointer
Aborted (core dumped)
The problem was indeed related to long long and that is why the code with int was running fine, because the fact that update would create an overflow, as the variable is a sum of two long long type variables which would have had max value LLONG_MAX assigned in main() was overlooked.
As long long can not accommodate 2*LLONG_MAX it was neither holding nor finding that value in the set of pairs used as the min heap. Thus iterator pointed to end of the set and erasing set.end() would generate undefined behavior in the long long datatype oriented code whereas it wouldn't in the int oriented one.
Replacing LLONG_MAX with 1e18 instead, in the code solved the problem and the code runs for all test files smoothly.
Additionally to clarify all the reasons that were pointed out through the comments, I thought I should clarify that not checking if dist.find(p) exists and doesn't point to end of set before performing dist.erase(dist.find(p)) would not create any problems. This is because it is Dijkstra's Algorithm and as many times as update is found to be less than previous, the node that this updated distance is being calculated for, from the source will always be present in the set paired with the distance previous. This is because all the nodes are initially entered with a value of 10e8 and are being updated as the values are found in successive iterations of the while loop.
Below is the working code, the only difference is that instead of LLONG_MAX I have used 1e18 and it runs fine on all test files including the one I had mentioned in the question as being problematic.
#include<bits/stdc++.h>
using namespace std;
# define ll long long int
ll update, previous;
set<pair<ll, int>> dist;
auto it=dist.begin();
int ind=0, n, i, j;
pair<ll, int>p;
void dij(vector<pair<int, ll>> tree[], bool decided[], ll d[], int path[]) {
ind=0;
while(!dist.empty()) {
it=dist.begin();
if(it==dist.end()) return;
ind=it->second;
dist.erase(it);
decided[ind]=1;
for(j=0; j<tree[ind].size(); j++) {
update=d[ind]+tree[ind][j].second;
previous=d[tree[ind][j].first];
if(update<previous) {
p=make_pair(previous, tree[ind][j].first);
//cout<<p.first<<" intermediate "<<p.second<<endl;
dist.erase(dist.find(p));
p=make_pair(update, tree[ind][j].first);
dist.insert(p);
path[tree[ind][j].first]=ind;
}
d[tree[ind][j].first]=min(update, previous);
}
}
}
int main()
{
ll edges;
ll x, y, weight;
cin>>n>>edges;
vector<pair<int, ll>> graph[n];
for(i=0; i<edges; i++) {
cin>>x>>y>>weight;
x--; y--;
graph[x].push_back({y, weight});
graph[y].push_back({x, weight});
}
int src=1;
src--;
ll d[n];
for(i=0; i<n; i++) {
if(src==i) {
dist.insert({0, i});
d[i]=0;
}
else {
dist.insert({1e18, i});
d[i]=1e18;
}
}
bool decided[n]={0};
int path[n]={-1};
for(int i=1; i<n; i++) path[i]=-2;
dij(graph, decided, d, path);
if(path[n-1]==-2) cout<<-1;
else {
vector<int> s;
int final=n-1;
while (final!=-1) {
s.push_back(final);
final=path[final];
}
reverse(s.begin(), s.end());
for(auto pi:s) cout<<pi+1<<" ";
}
cout<<endl;
}
Here is the output for the test file in the question:
Input
100 50
1 23 133
1 87 16
2 9 78
3 12 117
3 39 19
5 25 219
5 47 130
5 97 157
6 50 114
9 11 25
9 39 227
10 45 187
10 77 120
12 19 85
13 43 247
14 16 4
15 33 223
16 33 1
19 69 204
20 35 119
20 43 213
20 86 19
22 40 233
23 33 61
23 79 152
26 89 213
27 57 129
28 42 220
31 68 84
31 69 183
32 39 145
32 100 117
33 49 198
34 48 78
37 66 200
37 91 77
39 44 235
41 70 109
42 92 33
44 74 196
48 73 26
51 57 216
53 70 158
63 98 220
66 72 148
80 93 150
81 99 54
83 84 129
83 89 177
95 100 16
Participant's output
-1
Jury's answer
-1
The link to submission - Dijkstra

cycle detection in an undirected graph using dfs and height array

My job is to complete the isCyclic() function in following program. I can handle this job with visited array and passing parent to dfs() function but I am trying another solution, So I use a height array to keep track of distance of nodes in DFS tree for determining parents and cycle. this height array initial by zero. If distance of two node be exactly one these two node are parent child.
But I cannot understand why my solution doesn't work. can someone tell me why output of this code is not correct?
thanks for your help.
An example of graph and height value of nodes:
/*
.1
/ \
.2 .2
/ \
.3 .3
*/
#include<bits/stdc++.h>
using namespace std;
class Graph
{
int V;
list<int> *adj;
public :
Graph(int V);
void addEdge(int v,int w);
bool isCyclic();
};
vector<int> g[100001];
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v,int w)
{
adj[v].push_back(w);
adj[w].push_back(v);
}
int main()
{
int T;
cin>>T;
while(T--)
{
int _size,N;
cin>>_size>>N;
Graph *g = new Graph(_size);
for(int i=0;i<N;i++)
{
int u,v;
cin>>u>>v;
g->addEdge(u,v);
}
cout<<g->isCyclic()<<endl;
}
}
/*Please note that it's Function problem i.e.
you need to write your solution in the form of Function(s) only.
Driver Code to call/invoke your function is mentioned above.*/
/*The structure of the class is as follows
which contains an integer V denoting the no
of vertices and a list of adjacency vertices.
class Graph
{
int V;
list<int> *adj;
public :
Graph(int V);
void addEdge(int v,int w);
bool isCyclic();
};*/
/*You are required to complete this method*/
bool dfs(int v, int hi, list<int> *adj, int *h) {
h[v] = hi;
list<int>::iterator it;
for(it = adj[v].begin(); it != adj[v].end(); it++) {
int u = *it;
//cycle detect
if (h[u]>0 && hi - h[u] > 1)
return true;
if (h[u]==0 && dfs(u, hi+1, adj, h))
return true;
}
return false;
}
/*You are required to complete this method*/
bool Graph :: isCyclic()
{
//Your code here
int h[V];
for(int i = 0; i < V; i++) h[i] = 0;
for(int i = 0; i< V; i++)
if ( h[i] == 0 && dfs(i, 1, adj, h) ) return true;
return false;
}
A input that make my answer incorrect:
Input:
85 59
0 34 32 54 6 16 45 44 82 52 57 15 20 60 52 44 75 77 48 18 53 75 14 40 39 46 24 26 32 0 39 74 34 29 43 41 45 45 0 42 54 14 58 75 31 67 34 63 16 39 81 69 29 52 67 26 14 6 52 3 48 49 77 83 78 78 81 38 38 38 38 8 53 53 40 84 77 31 63 9 70 16 78 57 69 60 83 83 23 7 43 72 56 35 27 6 70 23 2 24 61 40 74 71 50 29 28 42 60 48 51 2 64 2 59 48 19 57
Its Correct output is:
1
And Your Code's output is:
0

error: cannot convert ‘double*’ to ‘double’ for argument ‘1’ and error: invalid types ‘double[double]’ for array subscript

I'm trying to bring in a partial data file to fill in an array and the user has three attempts to enter the correct data file name. I have repeatedly have gotten these errors. I understand that an array like arr is just a pointer to a block of memory.
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
void extract (double arr ,int n, double& i, int& error);
int main () {
double arr[256];
int n=256;
double i=0;
int error=0;
extract (arr,n,i,error);
return 0;
}
void extract (double arr, int n, double& i,int& error){
string infile;
string data="data.txt";cout <<"enter data file name/n";
cin >> infile;
while ((error<3) && (data.compare(infile) != 0)){
error++;
cout << "error in input. Please try again/n";
cin >> infile;
}
if (error<3){
ifstream fin;
fin.open("data.txt");
while ((i<n) && (fin >> arr[i])){
i++;
cout << arr[i] << " ";
}
fin.close();}
}
The errors occur in the while loop that inputs the data from the data file into the array.
Changing the Double i to int i replaced the old problem with
error: invalid types ‘double[int]’ for array subscript
Here is my data file
84
87
78
16
94
36
87
93
50
22
63
28
91
60
64
27
41
27
73
37
12
69
68
30
83
31
63
24
68
36
30
3
23
59
70
68
94
57
12
43
30
74
22
20
85
38
99
25
16
71
14
27
92
81
57
74
63
71
97
82
6
26
85
28
37
6
47
30
14
58
25
96
83
46
15
68
35
65
44
51
88
9
77
79
89
85
4
52
55
100
33
61
77
69
40
13
27
87
95
40
Change
void extract (double arr ,int n, double& i, int& error); to void extract (double* arr ,int n, double& i, int& error); both in the definition and declaration of extract function
Edit: The other error is because of double type variable being used as an array index, in your case i in extract function, so either change the type of i to int or use i = static_cast<int>(i) at the very start of extract function, I prefer the first way.
Here is the link of your code along with the changes done and it compiles and works perfectly.
Hope this helps

C++ merge sort passed by value

I am trying to recursively implement the merge sort algorithm by only passing in a vector value to the function (no left or right index). The while loop in the following code works when the list to be sorted is passed as a pointer void merge_sort_array(int* v, int l, int r) or reference void merge_sort_ref(vector<int>& v, int l, int r) but I cannot for the life of me understand why the following code will not properly sort my list. I have a feeling it is something to do with either the starting values of i, j, k or the bounds within my while loop but I've tried anything that makes sense to me and can't figure it out.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> merge_sort_value(vector<int> v) {
int n = v.size();
if(n == 1){
return v;
}
else{
int m = n/2;
vector<int> v1(v.begin(), v.begin()+m);
vector<int> v2(v.begin()+m, v.begin()+n);
merge_sort_value(v1);
merge_sort_value(v2);
vector<int> tmp(v.begin(), v.begin()+m);
int i = 0;
int j = m;
int k = 0;
while((i < m) or (j < n)){
if(i == m){
v[k] = v[j];
j +=1;
}
else if((j == n) or (tmp[i] < v[j])){
v[k] = tmp[i];
i+=1;
}
else{
v[k] = v[j];
j+=1;
}
k+=1;
# print output for debugging
for(auto x = v.begin(); x != v.end(); ++x)
cout << *x << " ";
cout << "" << endl;
cout << i << "\t"<< j << "\t" << k << endl;
}
return v;
}
}
int main(int argc, char** argv) {
vector<int> v(10);
for(int i=0; i < 10; ++i)
v[i] = rand() % 100;
v = merge_sort_value(v);
return 0;
}
I have included a sample output for reference below:
28 28
0 2 1
28 80
1 2 2
21 21
0 2 1
21 92
1 2 2
14 92 21
1 1 1
14 92 21
1 2 2
14 92 21
1 3 3
14 28 14 92 21
0 3 1
14 80 14 92 21
1 3 2
14 80 28 92 21
2 3 3
14 80 28 92 21
2 4 4
14 80 28 92 21
2 5 5
21 57
1 1 1
21 57
1 2 2
78 83
1 1 1
78 83
1 2 2
78 78 83
0 2 1
78 83 83
0 3 2
78 83 96
1 3 3
21 57 96 78 83
1 2 1
21 57 96 78 83
2 2 2
21 57 96 78 83
2 3 3
21 57 96 78 83
2 4 4
21 57 96 78 83
2 5 5
21 28 14 92 21 21 57 96 78 83
0 6 1
21 57 14 92 21 21 57 96 78 83
0 7 2
21 57 80 92 21 21 57 96 78 83
1 7 3
21 57 80 28 21 21 57 96 78 83
2 7 4
21 57 80 28 14 21 57 96 78 83
3 7 5
21 57 80 28 14 92 57 96 78 83
4 7 6
21 57 80 28 14 92 21 96 78 83
5 7 7
21 57 80 28 14 92 21 96 78 83
5 8 8
21 57 80 28 14 92 21 96 78 83
5 9 9
21 57 80 28 14 92 21 96 78 83
5 10 10
Thank you, any help is greatly appreciated!
after reviewing you code it seems you're making mistakes in the algorithm it self and in C++ as language so i've edited your algorithm to be more neat and more readable algorithm i will explain some part of the code
Code
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> merge_sort_value(vector<int> v) {
int n = v.size();
if(n == 1){
return v;
}
else{
int m = n/2;
vector<int> v1(v.begin(), v.begin()+m);
vector<int> v2(v.begin()+m, v.begin()+n);
v1 = merge_sort_value(v1); /* passing by value will left v1 with no sorting so you need to copy from the returned
object */
v2 = merge_sort_value(v2);
int i = 0;
int j = 0;
int k = 0;
const size_t left_vecS = v1.size();
const size_t right_vecS = v2.size();
while (i<left_vecS&&j<right_vecS) { // we must keep i (AND) j valid
if (v1[i] < v2[j])
v[k++] = v1[i++];
else
v[k++] = v2[j++];
}
while(i<left_vecS) // if we sorted v2 then what insert the rest of v1 in v as what kept from v1 will be sorted
v[k++] = v1[i++];
while(j<right_vecS)
v[k++] = v2[j++];
}
return v;
}
int main(int argc, char** argv) {
vector<int> v(10);
std::vector<int> x;
for(int i=0; i < 10; ++i)
v[i] = rand() % 100;
v = merge_sort_value(v);
for(auto&i:v)
std::cout << i << std::endl;
return 0;
}
1- I get rid of the printing inside the sorting function so we keep the code clean
2-
the first error you've did at the language level is you didn't copy the returned sorted vector object from merge_sort_value to the vectors.(i've mentioned that in the code in a comment) so that's the first thing to keep in mind
3- the logic part of the algorithm wasn't clear to me because i didn't see how you're sorting specially that part else if ((j == n) or (tmp[i] < v[j])) {
v[k] = tmp[i];
i += 1;
}
like you're comparing unsorted sub vector to another unsorted vector and you're giving it unsorted value again (you must compare v1 against v2)
the whole logic is missed up i think you need to review it
anyway i hope that helped

How to use MPI_Type_create_subarray?

It is clear that its arguments are:
int MPI_Type_create_subarray(
int ndims,
int array_of_sizes[],
int array_of_subsizes[],
int array_of_starts[],
int order,
MPI_Datatype oldtype,
MPI_Datatype *newtype
);
However, I cannot understand how this method receives the original array which we want to split and where it returns the new subarray (as this method should return an integer). In other words, I simply would like to see a simple implementation of this method in C++, which I am not able to find on the Internet.
MPI_Type_create_subarray() neither takes an original array nor returns a subarray; it creates an MPI type which describes the memory layout of a subarray given: a larger array of some given type; a set of subsizes; and a "corner" from which to start.
You can then use this newly created MPI type to extract just the data you want from any appropriately-sized array and send it in a message to another task (with point-to-point message passing routines), all other tasks (via collectives), or write it to disk (with MPI-IO). In the following example, rank 0 uses an MPI subarray type to extract a subarray from a larger array of integers and sends it to rank 1. Rank 1, just receiving it into a contiguous buffer, doesn't need to receive it as any special type; it just receives the data as so many integers.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void printarr(int **data, int n, char *str);
int **allocarray(int n);
int main(int argc, char **argv) {
/* array sizes */
const int bigsize =10;
const int subsize =5;
/* communications parameters */
const int sender =0;
const int receiver=1;
const int ourtag =2;
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < receiver+1) {
if (rank == 0)
fprintf(stderr,"%s: Needs at least %d processors.\n", argv[0], receiver+1);
MPI_Finalize();
return 1;
}
if (rank == sender) {
int **bigarray = allocarray(bigsize);
for (int i=0; i<bigsize; i++)
for (int j=0; j<bigsize; j++)
bigarray[i][j] = i*bigsize+j;
printarr(bigarray, bigsize, " Sender: Big array ");
MPI_Datatype mysubarray;
int starts[2] = {5,3};
int subsizes[2] = {subsize,subsize};
int bigsizes[2] = {bigsize, bigsize};
MPI_Type_create_subarray(2, bigsizes, subsizes, starts,
MPI_ORDER_C, MPI_INT, &mysubarray);
MPI_Type_commit(&mysubarray);
MPI_Send(&(bigarray[0][0]), 1, mysubarray, receiver, ourtag, MPI_COMM_WORLD);
MPI_Type_free(&mysubarray);
free(bigarray[0]);
free(bigarray);
} else if (rank == receiver) {
int **subarray = allocarray(subsize);
for (int i=0; i<subsize; i++)
for (int j=0; j<subsize; j++)
subarray[i][j] = 0;
MPI_Recv(&(subarray[0][0]), subsize*subsize, MPI_INT, sender, ourtag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printarr(subarray, subsize, " Receiver: Subarray -- after receive");
free(subarray[0]);
free(subarray);
}
MPI_Finalize();
return 0;
}
void printarr(int **data, int n, char *str) {
printf("-- %s --\n", str);
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
printf("%3d ", data[i][j]);
}
printf("\n");
}
}
int **allocarray(int n) {
int *data = malloc(n*n*sizeof(int));
int **arr = malloc(n*sizeof(int *));
for (int i=0; i<n; i++)
arr[i] = &(data[i*n]);
return arr;
}
Running this gives
$ mpicc -o subarray subarray.c -std=c99 -Wall -g
$ mpirun -np 2 ./subarray
-- Sender: Big array --
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
-- Receiver: Subarray -- after receive --
53 54 55 56 57
63 64 65 66 67
73 74 75 76 77
83 84 85 86 87
93 94 95 96 97