Using pointers to iterate through multidimensional array - c++

If you can use pointers to iterate through an array like this:
for (int *iter = arr; iter != std::end(arr); ++iter) {
// code
}
How do you iterate through a multidimensional array with pointers (without using auto)?
EDIT: I am assuming this is an int[][] such as {{3, 6, 8}, {2, 9, 3}, {4, 8, 2}}

If you declared array as arr[][], and yes you can because they are stored sequentially in memory. You can do:
for(int * iter = &arr[0][0]; iter != &arr[0][0] + col * row; iter++)
//...

How about trying like this:-
const int* d = data;
for ( int i = 0; i < width; ++i )
for ( int j = 0; j < height; ++j )
for ( int k = 0; k < depth; ++k )
sum += *d++;
Check this tutorial

For example:
constexpr size_t rowCnt = 3, colCnt = 4;
int ia[rowCnt][colCnt] = { // three elements; each element is an array of size 4
{0, 1, 2, 3}, // initializers for the row indexed by 0
{4, 5, 6, 7}, // initializers for the row indexed by 1
{8, 9, 10, 11} // initializers for the row indexed by 2
};
Not using a type alias for the type of the loop control variables:
// p points to the first array in ia
for (int (*p)[colCnt] = ia; p != ia + rowCnt; ++p) {
// q points to the first element of an array of four ints; that is, q points to an int
for (int *q = *p; q != *p + colCnt; ++q)
cout << *q << " ";
cout << endl;
}
or easier using auto:
for (auto p = ia; p != ia + rowCnt; ++p) {
// q points to the first element of an array of four ints; that is, q points to an int
for (auto q = *p; q != *p + colCnt; ++q)
cout << *q << " ";
cout << endl;
}

Improving texasbruce's answer(couldn't comment sorry) with sizeof trick, assuming array is statically allocated(dimensions are known at compile-time)
for(int * iter = &arr[0][0]; iter != &arr[0][0] + sizeof(arr)/sizeof(int); iter++)
or iter != (int*)((void*)&arr[0][0] + sizeof(arr)) if you're (void*) fan and hate any compile-time divisions
So you don't have to bother with array dimensions :)

Probably something like this
for (int **iter = arr; iter != std::end(arr); ++iter) {
for (int *iter2 = *iter; iter2 != std::end(*arr); ++iter2) {
// code
}
}

Assuming you are simply talking about statically declared multi-dimensional arrays:
const int ROWS = 10;
const int COLS = 20;
const int DEPTH = 30;
int array[ROWS][COLS][DEPTH]; // statically allocated array
int i = 0;
for (int row = 0; row < ROWS; ++row)
{
for (int col = 0; col < COLS; ++col)
{
for (int depth = 0; depth < DEPTH; ++depth)
{
*(*(*(array + row) + col) + depth) = i++; // do whatever with it
// is equivalent to array[row][col][depth] = i++;
}
}
}
If you need more levels, you just keep adding levels of pointer indirection.
Alternatively:
const int ROWS = 5;
const int COLS = 6;
const int DEPTH = 3;
int array[ROWS][COLS][DEPTH]; // statically allocated array
int* p = &array[0][0][0];
int c = 0;
for (int i = 0; i < ROWS * COLS * DEPTH; ++i, p++)
{
*p = c++;
}
Since a statically declared array is going to be contiguous in memory, with the first element (array[0][0][0]) starting at the base address (&array), this works.
Declaring a multi-dimensional array dynamically is going to be a pointer to an array of pointers to (etc) to pointers to an array of object_type. You can simplify that by using std::vector or std::array (if you know the size at compile time).
Not that these use pointers to iterate (at least not directly), but
Vector/Array
std::vector<std::vector<std::vector<int> > > array;
// or
//std::array<std::array<std::array<int, DEPTH>, COLS>, ROWS> array; // with some slight modifications
// fill in the vectors/arrays however you want
std::for_each(array.begin(), array.end(), [](const std::vector<std::vector<int> >& v)
{
std::for_each(v.begin(), v.end(), [](const std::vector<int>& a)
{
std::for_each(a.begin(), a.end(), [](int i)
{
std::cout << i << endl;
});
});
});

Related

Deleting an even number in an array and shift the elements

I'm trying to write a code where there is a research of even numbers and then it deletes the even numbers and then shifts all the other elements.
i is for offset and are the actual position of the elements in the array.
k is the position of the even number in the array.
int k;
for(i=0; i < N; i++)
{
if(Array[i] % 2 == 0)
{
for(k=i+1; k < N; k++)
{
Array[k-1] = Array[k];
}
N--;
}
}
Array=[2,10,3,5,8,7,3,3,7,10] the even numbers should be removed, but a 10
stays in the Array=[10,3,5,7,3,3,7].
Now is more than 3 hours that I'm trying to figure out what's wrong in my code.
This appears to be some sort of homework or school assignment. So what's the actual problem with the posted code?
It is that when you remove an even number at index i, you put the number that used to be at index i + 1 down into index i. Then you continue the outer loop iteration, which will check index i + 1, which is the number that was at the original i + 2 position in the array. So the number that started out at Array[i + 1], and is now in Array[i], is never checked.
A simple way to fix this is to decrement i when you decrement N.
Though already answered, I fail to see the reason people are driving this through a double for-loop, repetitively moving data over and over, with each reduction.
I completely concur with all the advice about using containers. Further, the algorithms solution doesn't require a container (you can use it on a native array), but containers still make it easier and cleaner. That said...
I described this algorithm in general-comment above. you don't need nested loops fr this. You need a read pointer and a write pointer. that's it.
#include <iostream>
size_t remove_even(int *arr, size_t n)
{
int *rptr = arr, *wptr = arr;
while (n-- > 0)
{
if (*rptr % 2 != 0)
*wptr++ = *rptr;
++rptr;
}
return (wptr - arr);
}
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
size_t n = remove_even(arr, sizeof arr / sizeof *arr);
for (size_t i=0; i<n; ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
Output
3 5 7 3 3 7
If you think it doesn't make a difference, I invite you to fill an array with a million random integers, then try both solutions (the nested-for-loop approach vs. what you see above).
Using std::remove_if on a native array.
Provided only for clarity, the code above basically does what the standard algorithm std::remove_if does. All we need do is provide iterators (the array offsets and size will work nicely), and know how to interpret the results.
#include <iostream>
#include <algorithm>
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
auto it = std::remove_if(std::begin(arr), std::end(arr),
[](int x){ return x%2 == 0; });
for (size_t i=0; i<(it - arr); ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
Same results.
The idiomatic solution in C++ would be to use a STL algorithm.
This example use a C-style array.
int Array[100] = {2,10,3,5,8,7,3,3,7,10};
int N = 10;
// our remove_if predicate
auto removeEvenExceptFirst10 = [first10 = true](int const& num) mutable {
if (num == 10 && first10) {
first10 = false;
return false;
}
return num % 2 == 0;
};
auto newN = std::remove_if(
std::begin(Array), std::begin(Array) + N,
removeEvenExceptFirst10
);
N = std::distance(std::begin(Array), newN);
Live demo
You could use a std::vector and the standard function std::erase_if + the vectors erase function to do this:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> Array = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
auto it = std::remove_if(
Array.begin(),
Array.end(),
[](int x) { return (x & 1) == 0 && x != 10; }
);
Array.erase(it, Array.end());
for(int x : Array) {
std::cout << x << "\n";
}
}
Output:
10
3
5
7
3
3
7
10
Edit: Doing it the hard way:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
for(size_t i = 0; i < N;) {
if((Array[i] & 1) == 0 && Array[i] != 10) {
for(size_t k = i + 1; k < N; ++k) {
Array[k - 1] = Array[k];
}
--N;
} else
++i; // only step i if you didn't shift the other values down
}
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}
Or simpler:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
size_t k = 0;
for(size_t i = 0; i < N; ++i) {
if((Array[i] & 1) || Array[i] == 10) {
// step k after having saved this value
Array[k++] = Array[i];
}
}
N = k;
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}

Summing the elements of two int vectors parallel to each other

I'm trying to get the sum of each element of two vectors and push the total to a new vector.
ie.
a = {1, 2 ,3} & b = {1, 2 ,3}
c = a + b
c = {2, 4, 6}
I've got it working for vectors of the same size, but whenever one of the vectors is larger than the other I get a vector subscript out of range error.
a = {1, 2 ,3} & b = {1, 2 ,3, 4}
c = a + b
I'm assuming this is happening during b[3] + ?? , how would I go about adding it so the output is:
c = {2, 4, 6, 4}
What i've got so far is:
vector<int> a = { 1,2,3,4 };
vector<int> b = { 5,4,3,2,1 };
vector<int> *vPtr;
vPtr = new vector<int>;
int sum;
int size = a.size();
if (size < b.size())
size = b.size();
for (unsigned i = 0; i < size; i++) {
sum = a[i] + b[i];
(*vPtr).push_back(sum);
}
for (vector<int>::const_iterator it = (*vPtr).begin(); it != (*vPtr).end(); it++)
cout << *it << " ";
cout << endl;
return 0;
Pad the smaller vector with extra zeros at the end. Here's an example:
int sizeDifference = abs(a.size() - b.size());
if(sizeDifference != 0){
if(a.size() > b.size())
for(int i = 0; i<sizeDifference; ++i)
b.push_back(0);
else
for(int i = 0; i<sizeDifference; ++i)
a.push_back(0);
}
Typically I do this with iterators in three parts. The part where both vectors have common elements. The part if/where a is longer than b and the part if/where b is longer than a.
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {4, 5, 6, 7};
std::vector<int> c;
// reserve enough space for the longest vector
c.reserve(std::max(a.size(), b.size()));
auto a_itr = std::begin(a);
auto b_itr = std::begin(b);
// for the part where the positions coincide
for(; a_itr != std::end(a) && b_itr != std::end(b); ++a_itr, ++b_itr)
c.push_back(*a_itr + *b_itr);
// for the part where a is longer than b (if any)
c.insert(std::end(c), a_itr, std::end(a));
// for the part where b is longer than a (if any)
c.insert(std::end(c), b_itr, std::end(b));
for(auto i: c)
std::cout << i << '\n';
size_type sm_size, lg_size;
vector<int> *lg_vec_ptr;
if (a.size < b.size()) {
sm_size = a.size();
lg_size = b.size();
lg_vector_ptr = &b;
} else {
sm_size = b.size();
lg_size = a.size();
lg_vector_ptr = &a;
}
vector<int> *sum_vec_ptr = new vector<int>;
size_type i;
for (i=0; i<sm_size; ++i)
sum_vec_ptr->push_back( a[i] + b[i] );
for ( ; i<lg_size; ++i)
sum_vec_ptr->push_back( lg_vector_ptr->[i] );
This method doesn't modify the original vectors.

Issue with int pointer in C++

int *sub(int *A,int q)
{
int i = id(A,q)+1,j = id(A,q)-1;
int *l , *m ;
m = (int*)malloc(sizeof(int));
*m = q;
l = m ;
for(i ; *(A+i) != '\0' && *(A + i) >= q ; ++i)
{
++l = (int*)malloc(sizeof(int));
*l = *(A+i);
}
++l = (int*)malloc(sizeof(int));
*l = '\0';
for(j ; j>=0 && *(A + j) >= q ; j--)
{
--m = (int*)malloc(sizeof(int));
*m = *(A+i);
}
for(i = 0 ; *(m + i) != '\0' ; i++)
cout<<*(m+i)<<"##\t";
return m;
}
It's a function that is supposed to take a pointer to a 1D array (A) and then return a pointer to another 1D array(m) which is subarray of A and has elements greater than or equal to q(passed as parameter to the function sub)
I guess there is some problem with the way I manipulate int pointers.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int q = 5;
std::vector<int> result;
std::copy_if(arr.begin(), arr.end(), std::back_inserter(result), [q](int i){return i >= q; });
std::for_each(result.begin(), result.end(), [](int i){std::cout << i << std::endl; });
getline(std::cin, std::string());
return 0;
}
You have no guarantee that m+i will ever be '\0', at least not for space that has been malloc'ed.
On top of the points mentioned in the comments, like making sure all space is freed appropriately. This just looks like a big memory leak all over the place.

How to compare and remove elements that does not have same value between 3 vectors?

I need to remove every elements that doesn't have same value between 3 vectors or more.
For example,
vector<int> Vector1, Vector2, Vector3;
for(int i = 2; i < 7; i++) Vector1.push_back(i); // Vector1 = {2, 3, 4, (5), (6)}
for(int i = 3; i < 8; i++) Vector2.push_back(i); // Vector2 = {3, 4, (5), (6), 7}
for(int i = 5; i < 10; i++) Vector3.push_back(i); // Vector3 = {(5), (6), 7, 8, 9}
We know that all of the vectors has 2 elements with same value: 5 and 6. Now how do I get these values and store them to a new vector?
Any kind of help would be appreciated :)
You have set_intersection in the standard algorithms library(vectors must be sorted):
// This code does it for two vectors only
vector<int> a, b, r;
for(int i = 0; i < 10; i++)
{
a.push_back(i);
b.push_back(i+5);
}
set_intersection(
a.begin(), a.end(),
b.begin(), b.end(),
back_inserter(r));
If all the vectors are ordered then you just scan them each time checking the lowest number until you pass it on one of the other two. if you can't find it, you drop it, each time you check the lowest number you get.
Example:
T1 = first element (v1)
T2 = firest elemnt (v2)
T3 = first element (v3)
find out the loweset one between the 3
if there is no equals - drop it and get the next val, and try again.
if all the vectors has the numbers going up (ordered) you'll find all matches.
For me the fastest solution is to build the set with elements from all vectors. Every time you inserts element that is not unique you increment his counter. Elements with counter equal numbers of vectors should be deleted.
However the simplest implementation is to make map (for most cases I think it is fast enough):
// only pseudo code
map<int,int> elems;
for( vector<int>& v : vectors )
for( int i : v ) {
map<int,int>::iterator itr = elems.find(i);
if( itr == elems.end() )
elems[i] = 1;
else itr->second++;
}
for( pair<int,int>& p : elems )
if( p.second == vectors.size() )
erase_from_vectors( p.first );
If your vectors are really huge you may build multimap that in value contains vector::iterators. Then you can remove those elements from vectors without looking through them.
If the vectors are not ordered and it is not possible to sort them, you can use this (in-efficient) approach:
#include <iostream>
#include <vector>
#include <algorithm>
typedef std::vector<int> IntVec;
typedef std::vector<IntVec> TwoDIntVec;
IntVec
intvec_union(const TwoDIntVec& vec)
{
IntVec result;
size_t vec_size = vec.size();
if (vec_size < 3) return result;
const IntVec& vec1 = vec[0];
size_t sz = vec1.size();
for (size_t i=0; i<sz; ++i)
{
bool found = true;
int val = vec1[i];
for (size_t j=1; j<vec_size; ++j)
{
const IntVec& v = vec[j];
if (std::find(v.begin(), v.end(), val) == v.end())
{
found = false;
break;
}
}
if (found) result.push_back(val);
}
return result;
}
// test
int
main()
{
IntVec Vector1, Vector2, Vector3;
for(int i = 2; i < 7; i++) Vector1.push_back(i); // Vector1 = {2, 3, 4, (5), (6)}
for(int i = 3; i < 8; i++) Vector2.push_back(i); // Vector2 = {3, 4, (5), (6), 7}
for(int i = 5; i < 10; i++) Vector3.push_back(i); // Vector3 = {(5), (6), 7, 8, 9}
TwoDIntVec v;
v.push_back(Vector1);
v.push_back(Vector2);
v.push_back(Vector3);
IntVec result = intvec_union(v); // result = {5,6}
return 0;
}
This seems to work, although it looks ugly:
void intersection(std::vector<std::vector<int>*> valList, std::vector<int>& intersectionList)
{
if(valList.size() < 2)
{
return;
}
std::vector<std::vector<int>*>::iterator iter = valList.begin();
std::vector<std::vector<int>*>::iterator endIter = valList.end();
for(; iter != endIter; ++iter)
{
std::vector<int>* pVec = *iter;
std::sort(pVec->begin(), pVec->end());
}
iter = valList.begin();
endIter = valList.end();
std::vector<int>* pFirstVec = *iter;
std::vector<int>* pSecondVec = *(iter + 1);
iter = iter + 2;
std::set_intersection(pFirstVec->begin(), pFirstVec->end(), pSecondVec->begin(), pSecondVec->end(), std::back_inserter(intersectionList));
for(; iter != endIter; ++iter)
{
std::vector<int> temp;
std::vector<int>* pVec = *iter;
std::set_intersection(pVec->begin(), pVec->end(), intersectionList.begin(), intersectionList.end(), std::back_inserter(temp));
intersectionList = temp;
std::sort(intersectionList.begin(), intersectionList.end());
}
}
int main()
{
std::vector<int> Vector1, Vector2, Vector3, Vector4;
for(int i = 2; i < 7; i++) Vector1.push_back(i); // Vector1 = {2, 3, 4, (5), (6)}
for(int i = 3; i < 8; i++) Vector2.push_back(i); // Vector2 = {3, 4, (5), (6), 7}
for(int i = 5; i < 10; i++) Vector3.push_back(i); // Vector3 = {(5), (6), 7, 8, 9}
for(int i = 6; i < 12; i++) Vector4.push_back(i); // Vector3 = {(6),7,8,9,10,11}
std::vector<int> r;
std::vector<std::vector<int>*> v;
v.push_back(&Vector1);
v.push_back(&Vector2);
v.push_back(&Vector3);
v.push_back(&Vector4);
intersection(v,r);
return 0;
}
Other answers seems to assume that the vectors are sorted or don't have repeated values (I think gba's answer fails in that case).
This one works in every cases and still try to be efficient. It removes all elements found in every vectors.
template <class C>
struct is_in{
const C & c_;
bool b_;
is_in(C c, bool b = true) : c_(c), b_(b) {}
bool operator() (typename C::value_type v){
return b_ == (c_.find(v) != c_.end());
}
};
int main() {
set<int> s(v.front().begin(), v.front().end());
typedef is_in<set<int> > is_in_set;
vector< vector<int> >::iterator i;
for(i = v.begin()+1; i != v.end(); ++i) {
//s is the intersection of every vectors before i
set<int> new_s;
//copy in new_s all elements of *i unless they are not in s
remove_copy_if(i->begin(), i->end(), insert_iterator<set<int> >(new_s, new_s.begin()),
is_in_set(s, false));
swap(s, new_s);
}
for(i = v.begin(); i != v.end(); ++i) {
//erase all elements of *i which are in s
i->erase(remove_if(i->begin(), i->end(),
is_in_set(s)), i->end());
}
vector<int> res_vec(s.begin(), s.end());
}
This approach relies on having sorted input vectors, but after that will only do an linear walk through the current and next vectors to be compared, keeping the matching elements in the first vector. It doesn need to do a full search for each element. The algorithm is reasonably container neutral, requiring only forward iterators so will work with vectors, lists, singly linked lists, raw arrays, etc.
The essential building block for this algorithm is a function that removes elements from a sorted range that aren't in a second sorted range. I'm using the std::remove convention of swapping unwanted elements to the end of the range and returning an iterator pointing to start of the unwanted elements. It's O(n + m).
template<class Input1, class Input2>
Input1 inplace_intersection(Input1 first1, Input1 last1, Input2 first2, Input2 last2)
{
using std::swap;
Input1 nextslot(first1);
for( ; first1 != last1; ++first1 )
{
// Skip elements from the second range that are
// smaller than the current element.
while( first2 != last2 && *first2 < *first1 )
++first2;
// Do we have a match? If so keep
if( first2 != last2 && !(*first1 < *first2) )
{
if( first1 != nextslot )
swap( *first1, *nextslot );
++nextslot;
}
}
return nextslot;
}
With this building block you can operate on sorted vectors this.
std::vector<int> initial;
// fill...
std::vector<int>::iterator first = initial.begin(), last = initial.end();
last = inplace_intersection( first, last, scnd.begin(), scnd.end() );
last = inplace_intersection( first, last, thrd.begin(), thrd.end() );
// etc...
initial.erase( last, erase.end() );
If your input vectors aren't sorted, then you can sort them in place if possible, or otherwise create sorted copies.

How does one rank an array (sort) by value? *With a twist*

I would like to sort an array in ascending order using C/C++. The outcome is an array containing element indexes. Each index is corespondent to the element location in the sorted array.
Example
Input: 1, 3, 4, 9, 6
Output: 1, 2, 3, 5, 4
Edit: I am using shell sort procedure. The duplicate value indexes are arbitrarily chosen based on which duplicate values are first in the original array.
Update:
Despite my best efforts, I haven't been able to implement a sorting algorithm for an array of pointers. The current example won't compile.
Could someone please tell me what's wrong?
I'd very much appreciate some help!
void SortArray(int ** pArray, int ArrayLength)
{
int i, j, flag = 1; // set flag to 1 to begin initial pass
int * temp; // holding variable orig with no *
for (i = 1; (i <= ArrayLength) && flag; i++)
{
flag = 0;
for (j = 0; j < (ArrayLength - 1); j++)
{
if (*pArray[j + 1] > *pArray[j]) // ascending order simply changes to <
{
&temp = &pArray[j]; // swap elements
&pArray[j] = &pArray[j + 1]; //the problem lies somewhere in here
&pArray[j + 1] = &temp;
flag = 1; // indicates that a swap occurred.
}
}
}
};
Since you're using C++, I would do it something like this. The SortIntPointers function can be any sort algorithm, the important part is that it sorts the array of pointers based on the int that they are pointing to. Once that is done, you can go through the array of pointers and assign their sorted index which will end up in the original position in the original array.
int* intArray; // set somewhere else
int arrayLen; // set somewhere else
int** pintArray = new int*[arrayLen];
for(int i = 0; i < arrayLen; ++i)
{
pintArray[i] = &intArray[i];
}
// This function sorts the pointers according to the values they
// point to. In effect, it sorts intArray without losing the positional
// information.
SortIntPointers(pintArray, arrayLen);
// Dereference the pointers and assign their sorted position.
for(int i = 0; i < arrayLen; ++i)
{
*pintArray[i] = i;
}
Hopefully that's clear enough.
Ok, here is my atempt in C++
#include <iostream>
#include <algorithm>
struct mycomparison
{
bool operator() (int* lhs, int* rhs) {return (*lhs) < (*rhs);}
};
int main(int argc, char* argv[])
{
int myarray[] = {1, 3, 6, 2, 4, 9, 5, 12, 10};
const size_t size = sizeof(myarray) / sizeof(myarray[0]);
int *arrayofpointers[size];
for(int i = 0; i < size; ++i)
{
arrayofpointers[i] = myarray + i;
}
std::sort(arrayofpointers, arrayofpointers + size, mycomparison());
for(int i = 0; i < size; ++i)
{
*arrayofpointers[i] = i + 1;
}
for(int i = 0; i < size; ++i)
{
std::cout << myarray[i] << " ";
}
std::cout << std::endl;
return 0;
}
create a new array with increasing values from 0 to n-1 (where n is the length of the array you want to sort). Then sort the new array based on the values in the old array indexed by the values in the new array.
For example, if you use bubble sort (easy to explain), then instead of comparing the values in the new array, you compare the values in the old array at the position indexed by a value in the new array:
function bubbleRank(A){
var B = new Array();
for(var i=0; i<A.length; i++){
B[i] = i;
}
do{
swapped = false;
for(var i=0; i<A.length; i++){
if(A[B[i]] > A[B[i+1]]){
var temp = B[i];
B[i] = B[i+1];
B[i+1] = temp;
swapped = true;
}
}
}while(swapped);
return B;
}
create a new Array and use bubble sort to rank the elements
int arr[n];
int rank[n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(arr[i]>arr[j])
rank[i]++;
The rank of each element will be rank[i]+1 to be in the order of 1,2,....n
Well, there's a trival n^2 solution.
In python:
newArray = sorted(oldArray)
blankArray = [0] * len(oldArray)
for i in xrange(len(newArray)):
dex = oldArray.index(newArray[i])
blankArray[dex] = i
Depending on how large your list is, this may work. If your list is very long, you'll need to do some strange parallel array sorting, which doesn't look like much fun and is a quick way to introduce extra bugs in your code.
Also note that the above code assumes unique values in oldArray. If that's not the case, you'll need to do some post processing to solve tied values.
Parallel sorting of vector using boost::lambda...
std::vector<int> intVector;
std::vector<int> rank;
// set up values according to your example...
intVector.push_back( 1 );
intVector.push_back( 3 );
intVector.push_back( 4 );
intVector.push_back( 9 );
intVector.push_back( 6 );
for( int i = 0; i < intVector.size(); ++i )
{
rank.push_back( i );
}
using namespace boost::lambda;
std::sort(
rank.begin(), rank.end(),
var( intVector )[ _1 ] < var( intVector )[ _2 ]
);
//... and because you wanted to replace the values of the original with
// their rank
intVector = rank;
Note: I used vectorS instead of arrays because it is clearer/easier, also, I used C-style indexing which starts counting from 0, not 1.
This is a solution in c language
#include <stdio.h>
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// A function to implement bubble sort
void bubbleSort(int arr[], int n) {
int i, j;
for (i = 0; i < n - 1; i++)
// Last i elements are already in place
for (j = 0; j < n - i - 1; j++)
if (arr[j] > arr[j + 1])
swap(&arr[j], &arr[j + 1]);
}
/* Function to print an array */
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 98};
int arr_original[] = {64, 34, 25, 12, 22, 11, 98};
int rank[7];
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
//PLACE RANK
//look for location of number in original array
//place the location in rank array
int counter = 1;
for (int k = 0; k < n; k++){
for (int i = 0; i < n; i++){
printf("Checking..%d\n", i);
if (arr_original[i] == arr[k]){
rank[i] = counter;
counter++;
printf("Found..%d\n", i);
}
}
}
printf("Original array: \n");
printArray(arr_original, n);
printf("Rank array: \n");
printArray(rank, n);
return 0;
}