Sorting a 2d array - c++

I am trying to sort two sets of data, that are either in a 2d array or parallel arrays, either way it makes no difference but I cant seem to figure it out. Here are the two arrays:
/////way one///
int id[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int numDetected[10] = {40, 21, 2, 19, 45, 32,43, 90, 100, 8};
or
int 2dArray[2][10];
it makes no difference, but I cant seem to figure this out.
I want to order the arrays into a new array, (whether it is a 2d array or parrellel arrays) by the numDetected amount. So the largest numDetected is at element zero and the smallest at the end. But while doing that, I want to keep the id associated with that in the same element as the numDetected. So if numDetected[2] is the largest, I want numDetected[2] and id[2] to be the first elements in the new arrays.
Can anyone help me out?

struct values
{
int id;
int detected;
} data[10] = ...;
// intentionally reversed to cause sort in descending order
bool operator<(const values& left, const values& right) { return left.detected > right.deteted; }
values *begin = data, *end = (&data)[1];
std::sort(begin, end);

Related

Sort multidimensional array and keep index C++

Is it possible to sort a multidimensional array (row by row) using sort in C++ such that I can keep the index?
For example,
13, 14, 5, 16
0, 4, 3, 2
7, 3, 7, 6
9, 1, 11, 12
Becomes:
{ 5,13,14,16}
{ 0,2,3,4 }
{ 3,6,7,7}
{ 1,9,11,12 }
And the array with the index would be:
{2,0,1,3}
{0,3,2,1}
{1,3,0,2}
{ 1,0,2,3}
First create the array of integer indices; here it is for 1D array:
int ind[arr.size()];
for( int i=0; i<arr.size(); ++i)
ind[i] = i;
Then create the comparison object. Here is a ballpark of that in C++99 lingo; for C++11 you can shortcut that by using a lambda:
struct compare
{
bool operator()( int left, int right ) {
return arr[left] < arr[right];
}
};
The sort the index array using that functor:
std::sort( ind, ind+sizeof(arr), compare );
Finally, use the sorted index array to order the values array.
Yes. To sort row by row, you have to set the appropriate starting and ending point in the sort function.To keep the index part, you can first create pairs of the array elements and index using the make_pair command. After executing the above code, you can reconstruct the index array.
You will need to do something like this (I haven't tried it out though):
for (i = 0; i < matrix.size(); i++)
{
sort(matrix[i].begin(), matrix[i].end());
}
Remember to add the index as the second element in the pair, because the default comparision operator for pairs checks the first element, followed by the second element.

C++ casting static two-dimensional double array to double**

I have such matrix in my program:
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
And I'd like to cast it to double** type.
I've already tried simple double** a = (double**)m;, but it doesn't work (when I try to read any value, I get "Access violation reading location 0x00000000.", which means I'm trying to read from NULL adress.
I found almost working solution:
double *b = &m[0][0];
double **c = &b;
It works when I read field c[0][any]
But same NULL adress reading problem occurs, when I try to read value from field c[1][0].
What is the proper way to cast my double m[3][4] array to type double**?
edit:
You say that's impossible. So I'll change a problem a little bit. How can I pass two-dimensional double array as a parameter to a function? My function has prototype:
void calculate(double **matrix, int n); //where matrix size is always n by n+1
And it's working fine with dynamically-allocated arrays. I doubt that only way to make it work is allocating new dynamical array and copy original static array one element by another...
You can't.
The notation double** refers to an array of pointers. You don't have an array of pointers, you have an array of arrays of doubles.
You can't just cast the array. You are going to have to create something like this:
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
double *marray[3] = {m[0],m[1],m[2]};
calculate(marray,3);
Or you can use a loop:
const size_t n = 3;
double *marray[n];
for (size_t i=0; i!=n; ++i) {
marray[i] = m[i];
}
calculate(marray,n);
When you write
double m[3][4]
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
The compiler actually creates an array of doubles as if you had written
double _m[] = {2, 4, 5, 7, 4, 5, 1, 12, 9, 12, 13, -4};
However, thanks to C/C++ type system, the compiler remembers that m's type
is double [3][4]. In particular it remembers the sizes 3 and 4.
When you write
m[i][j]
the compiler replaces it by
_m[i * 4 + j];
(The 4 comes from the second size in double [3][4].) For instance,
m[1][2] == 1 and _m[1 * 4 + 2] == _m[6] == 1 as well.
As others said, a double** is a different type which doesn't carry the
sizes with it. To consider double** a as a 3 x 4 matrix, a[0], a[1] and
a[2] must be pointers to double (that is, double*) pointing to the
first element of the corresponding row. You can achieve this with
double* rows[] = { &m[0][0], &m[1][0], &m[2][0] };
double** a = &rows[0];
A simple cast doesn't create the variable rows above. Let me present other
alternative (but equivalent) ways to define rows
double* rows[] = { &m[0][0], &m[0][0] + 4, &m[0][0] + 2 * 4};
double* rows[] = { &_m[0], &_m[4], &_m[2 * 4]};
As you can see, only the second size (i.e. 4) is necessary. In general, for
multi-dimensional arrays, all sizes but the first are required. For this
reason a 1-dimensional array
double x[4] = { 1, 2, 3, 4 };
can be implicitly converted to a double*
double* y = x;
Using this fact we can also write
double* rows[] = { _m, _m + 4, _m + 2 * 4};
Indeed, _m is converted to a double* pointing to m[0]. Then, in _m + 4,
_m is is converted to a double* pointing to m[0] and to this pointer
it's added 4. Hence, _m + 4 is a pointer the fourth double following
_m[0], which is _m[4] and so on.
So far I have explained why you cannot cast a double [3][4] (or any other sizes) to a double**. Now, I'shall show, in your particular case, how calculate can be defined.
template <int N>
void calculate(double (&m)[N][N+1]) {
// use m as a double[N][N+1]
}
You call
calculate(m);
and the compiler will deduce the size N for you. In general (i.e, when the second dimension is not the N + 1) you can write
template <int N, int M>
void calculate(double (&m)[N][M]) {
// use m as a double[N][M]
}
If you're always using arrays (no pointers) for initialization, and you are able to avoid the pointer stuff in your calculate function, you might consider the following option, which uses size deduction by templates.
template<int m, int n>
void doubleFunc(double (&mat)[m][n])
{
for (auto i = 0; i < m; i++)
{
for (auto j = 0; j < n; j++)
{
std::cout << mat[i][j] << std::endl;
}
}
}
It worked during my quick test.
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
doubleFunc(m);
You can pass a 2d array as a function parameter:
void calculate(double matrix[][y], int n);
Until variable-length arrays are in the C++ standard, your choices include:
If your compiler supports variable-length arrays as an extension, you can likely pass them with a function declaration such as void foo(std::size_t n, double a[][n+1]). Note that the compiler likely requires n to be passed before a parameter declaration that uses n or requires some special syntax.
You can pass a double * and do index arithmetic manually in the function: void foo(std::size_t n, double *a) { … a[row*(n+1) + column] … }
You can create a class the implements variable-length arrays by doing the index arithmetic in its accessor functions.
You can allocate space for n pointers to double, fill those pointers with pointers to each row of the array, and pass the address of the space.

c++ arrays, how to add a new row of values in the same array?

how do you create a new row of values in an array from user input or cin?
say theres a row of values already in the array and you need to add a second row of values
but not added to the first row, and how would you put the braces and the comma in, does the user put it in or is there something that will automatically put the bracers and comma in
int test [] = { 1, 21, 771, 410, 120711 },
{ 1, 2, 3, 4, 5 };
Without very bad and dirty tricks this is not possible. Better use list or vector (which is the nearest to an array). The other possibility is to use pointers and to extend it create a temporary memory, copy the old data and then add the new.
There is no way to change the size of array while still preserving its contents. The only way to change the size of an array at all is to use the new operator to allocate dynamic memory to a pointer, but this will destroy any data the array previously held. If you want to have a re-sizable array, you should probably use std::vector.
If you're keen on using c++11 you can keep your initialiser lists with std::vector like so:
#include <vector>
int main()
{
// initialise
std::vector<std::vector<int>> test = { { 1, 21, 771, 410, 120711 },
{ 1, 2, 3, 4, 5 } };
// add new data from user
test.push_back({9, 8, 7, 6, 5, 4, 3, 2, 1});
}
You're asking for a two-dimensional array. This is declared like this:
int test[][5] = {
{1, 21, 771, 410, 120711},
{1, 2, 3, 4, 5 },
// Add more if you want.
};
The first array is accessed through test[0], the second through test[1], etc. The first element of the first array is test[0][0], the second test[0][1] and so forth.
Note that this is an array with a static size. You can't change it at runtime. If you know in advance how many rows you need, you just declare it as:
int test[NUMBER OF ROWS][NUMBER OF COLUMNS];
and then fill it with values later. But you cannot change the size. If you want a fully dynamic array, then you should use a vector of vectors:
std::vector< std::vector<int> > test;
You then add rows with:
test.push_back(std::vector<int>());
and add elements to each row with:
// Adds a number to the first row.
test[0].push_back(some_int);
Access happens the same way as with the static array (test[0], test[0][0], etc.)

How do i select the other column in a 2-dimensional array?

How do i select the second column of a 2-dimensional array.
I have this array with about 30 values (LKT) and from there I have a 2-dimensional array (ScaledValues). The 2nd column of this 2-dimensional array will be filled with a scaled version of the original LKT array.
Initially, ActiveArray variable points to the LKT array. However, when I populate the 2nd column of the array in ScaledValues with scaled values of the first LKT array, how do I move ActiveArray to now point to the second column as the active array that i'll be using? i.e. After i fill the second column with the desired scale values, I'd like to work with those values and I want to use ActiveArray variable to denote that this new column is the active array.
I know there are other ways to do this i.e. I could create 2 separate individual arrays but I have to use the format that you see below. please assist. thanks.
Please let me know if i need to make my question clearer.
Thank you very much.
static const unsigned int LKT[30] = {
30, 29, 28, 27, 26, 25, 24, 23, 22,
21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
static unsigned int ScaledValues[30][2];
static volatile unsigned char ActiveArray = 0;
Reverse the ScaledValues array declaration:
unsigned int ScaledValues[2][30];
for (int i = 0; i < 30; i++) {
ScaledValues[0][i] = LKT[i];
ScaledValues[1][i] = scale(LKT[i]);
}
// Also need to make this a pointer
unsigned int * ActiveArray = ScaledValues[0]; // Original values
ActiveArray = ScaledValues[1]; // Scaled values
the easier way to manipulate this array could be done as following
first the definition should be in this way
static unsigned int ScaledValues[2][30];
then to copy LKT to the first line (and not column)
memcpy(ScaledValues[0], LKT, 30*sizeof(unsigned int));
to access to the second line of the ScaledValues array is
ScaledValues[1]

HOW TO CREATE a multy MAP for 3 data sets

I have a huge amount of data set. I wish to use array to store these data. In more deatil,
In my array, i want to use 3 columns such as Number number_of_points point_numbers. For this i can create a array like mypointstore[][] (for example mypointstore[20][3]). But my problem is that i want to store point numbers in column 3 like, 20, 1, 32, 9, 200, 12 and etc.(mypointstore[0][0]= 1, mypointstore[0][1]= 6 and mypointstore[0][2]={ 20, 1, 32, 9, 200, 12 }). I don’t know that is it posible to use array for this structure? If so, please help me to solve this problem.
I tried to use map like map<int,int,vector<int>> mypointstore; but i don’t know how to insert data into this map;
My some codes are here
map<int,int, vector<int>> mypointstore;
size=20;
For (int i=0; i<= size;i++){
Int det=0;
For (int j=0; j<= points.size();j++){//points is a one of array with my points
If (points.at(j)>Z1 && points.at(j) <=Z2){
//Here i want to store i , det and poiznts.at(j) like i in 1st colum, det in 2nd and
//pointnumber in 3rd colum) in each step of the loop it take a point
//number //which satisfied the if condition so it should be include into my
// vector of map
det++;
}
}
// at here i want to change total det value into 2nd element of my map so it like (0)(6)( 20, 1, 32, 9, 200, 12)
}
similar procedure for the next step so finaly it should be
(0)(6)( 20, 1, 32, 9, 200, 12)
(1)(10)( 20, 1, 32, 9, 200, 12, 233, 80, 12, 90)
(2)(3)( 3, 15, 32)
It sounds to me like you probably want a vector of structs, something like:
struct point_data {
int number;
std::vector<int> point_numbers;
};
std::vector<point_data> points;
I've only put in two "columns", because (at least as I understand it) your number_of_points is probably point_numbers.size().
If you're going to use the number to find the rest of the data, then your idea to use a map would make sense:
std::map<int, std:vector<int> > points;
You could use a multimap<int, int> instead of map<int, vector<int> > but I usually find the latter more understandable.