Sorting

S

Speed

Hi,

I have an array that I want to sort without losing the index
information.

For eg. sorting X[5] = {34.5, 56.4, 12.9, 43.2, 21.7};

should return {2, 4, 0, 3, 1}

Could you please tell me how to do it quickly.

Many thanks,
Speed.
 
E

Eric Sosman

Speed said:
Hi,

I have an array that I want to sort without losing the index
information.

For eg. sorting X[5] = {34.5, 56.4, 12.9, 43.2, 21.7};

should return {2, 4, 0, 3, 1}

Could you please tell me how to do it quickly.

Solution #1: Instead of the "bare" array X[], sort an array
of structs where each struct holds an X value and its index:

struct { double val; int idx; } X[] = {
{ 34.5, 0 }, { 56.4, 1 }, { 12.9, 2}, ... };

Solution #2: Leave X[] alone and instead sort an array of
indices to it:

double X[] = { 34.5, 56.4, 12.9, ... };
double I[] = { 0, 1, 2, ... };

While sorting I[] you will need to decide how I[j] and I[k]
are ordered, for various j and k. Make the decision by
comparing X[I[j]] with X[I[k]].
 
W

Willem

Speed wrote:
) I have an array that I want to sort without losing the index
) information.
)
) For eg. sorting X[5] = {34.5, 56.4, 12.9, 43.2, 21.7};
)
) should return {2, 4, 0, 3, 1}
)
) Could you please tell me how to do it quickly.

Start with {0,1,2,3,4}. Sort this, using X[a] <=> X as operator.

The qsort() library function is usually your best bet.


NB: The <=> operator is not C. I use it as shorthand for:
X[a] < X ? -1 : X[a] > X


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
E

Eric Sosman

Eric said:
[...]
Solution #2: Leave X[] alone and instead sort an array of
indices to it:

double X[] = { 34.5, 56.4, 12.9, ... };
double I[] = { 0, 1, 2, ... };
[...]

Oh, rats. `int I[]', of course, or even `size_t I[]'
if you anticipate sorting large arrays. Sorry about that.
 
S

Speed

Speed wrote:

) I have an array that I want to sort without losing the index
) information.
)
) For eg. sorting X[5] = {34.5, 56.4, 12.9, 43.2, 21.7};
)
) should return {2, 4, 0, 3, 1}
)
) Could you please tell me how to do it quickly.

Start with {0,1,2,3,4}. Sort this, using X[a] <=> X as operator.

The qsort() library function is usually your best bet.

NB: The <=> operator is not C. I use it as shorthand for:
X[a] < X ? -1 : X[a] > X

SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT


Hi,

Many thanks for the replies. I am not quite sure how to use qsort() to
sort the array of indices. Could you please tell me how to call with
indices?

Many thanks,
Speed.
 
W

Willem

Speed wrote:
) Many thanks for the replies. I am not quite sure how to use qsort() to
) sort the array of indices. Could you please tell me how to call with
) indices?

I don't know the details of what you're trying to achieve, so how about
you post whatever you think looks like a reasonable piece of code that
tries to do what you want, and then some of the people on this newsgroup
will undoubtedly help out with the bits that aren't working for you.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
S

Speed

Speed wrote:

) Many thanks for the replies. I am not quite sure how to use qsort() to
) sort the array of indices. Could you please tell me how to call with
) indices?

I don't know the details of what you're trying to achieve, so how about
you post whatever you think looks like a reasonable piece of code that
tries to do what you want, and then some of the people on this newsgroup
will undoubtedly help out with the bits that aren't working for you.

SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Hi,

Managed to put together some code. It works fine now but I needed to
make the Data[] into a global variable. Is there any way of passing
the Data[] to qsort() along with the Index_Array[]?

// Global Variable declaration for Data[]
FLOAT64 Data[100];

// Comparator Function for qsort
int compare_index(const void* a, const void* b )
{
int* arg1 = (int*) a;
int* arg2 = (int*) b;
if(Data[*arg1] < Data[*arg2])
{
return -1;
}
else
{
if(Data[*arg1] == Data[*arg2])
{
return 0;
}
else
{
return 1;
}
}
}

int main()
{
.
.
.

// Generate Index Array
int Index_Array[100];
for (i = 0; i < iCnt; i++)
{
Index_Array = i;
}

// Sort Index Array
qsort(Index_Array, Number_of_Elements, sizeof(int),
compare_index);
}

Many thanks,
Speed.
 
W

Willem

Speed wrote:
) Hi,
)
) Managed to put together some code. It works fine now but I needed to
) make the Data[] into a global variable. Is there any way of passing
) the Data[] to qsort() along with the Index_Array[]?

Not that I know of, I'm afraid. That's one of the major drawbacks of
the C qsort() function, actually. The best you can do is have a global
pointer to get to the Data[], I think.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Richard Heathfield

Willem said:
Speed wrote:
) Hi,
)
) Managed to put together some code. It works fine now but I needed to
) make the Data[] into a global variable. Is there any way of passing
) the Data[] to qsort() along with the Index_Array[]?

Not that I know of, I'm afraid. That's one of the major drawbacks of
the C qsort() function, actually. The best you can do is have a global
pointer to get to the Data[], I think.

Um, why not just sort pointers?

Taking the original example:

struct foo
{
double *ptr;
size_t idx;
};

#define N 5

double X[N] = {34.5, 56.4, 12.9, 43.2, 21.7};
struct foo Index_Array[N] = {0};

for(i = 0; i < N; i++)
{
Index_Array.ptr = X + i;
Index_Array.idx = i;
}

qsort(Index_Array, N, sizeof Index_Array[0], cmpfoo);

and of course we need:

int cmpfoo(const void *vleft, const void *vright)
{
const struct foo *left = vleft;
const struct foo *right = vright;
return (*left->ptr < *right->ptr) - (*left->ptr > *right->ptr);
}
 
W

Willem

Richard wrote:
) Willem said:
)> Speed wrote:
)> ) Hi,
)> )
)> ) Managed to put together some code. It works fine now but I needed to
)> ) make the Data[] into a global variable. Is there any way of passing
)> ) the Data[] to qsort() along with the Index_Array[]?
)>
)> Not that I know of, I'm afraid. That's one of the major drawbacks of
)> the C qsort() function, actually. The best you can do is have a global
)> pointer to get to the Data[], I think.
)
) Um, why not just sort pointers?
)
) Taking the original example:
)
) struct foo
) {
) double *ptr;
) size_t idx;
) };

Good idea, although that doubles the amount of data that qsort
has to shuffle. But maybe we can do without. How about:

#define N 5

double X[N] = {34.5, 56.4, 12.9, 43.2, 21.7};
double *Pointer_Array[N];
size_t Index_Array[N];

for(i = 0; i < N; i++)
{
Pointer_Array = X + i;
}

qsort(Pointer_Array, N, sizeof Pointer_Array[0], cmpdouble);

And then:

for (i = 0; i < N; i++)
{
Index_Array = Pointer_Array - X;
}


With the obvious compare function:

int cmpdouble(const void *vleft, const void *vright)
{
const double *left = vleft;
const double *right = vright;
return (*left < *right) - (*left > *right);
}

Although that's still a lot of extra overhead just to avoid
a global pointer.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Richard Heathfield

Willem said:
Richard wrote:

Please retain my surname when quoting, Willem - not because I'm precious
about it or anything, but simply to disambiguate me from the Riley troll.
Thanks.
)
) Um, why not just sort pointers?

Good idea, although that doubles the amount of data that qsort
has to shuffle. But maybe we can do without. How about:

Yes, as soon as you said "although that doubles", I thought of a way to do
without. (Yes, same way that you thought of, although it took me a little
longer!)

Although that's still a lot of extra overhead just to avoid
a global pointer.

<shrug> It's a point of view. Some people would see the overhead as
insignificant compared to the maintainability issues of file scope
objects.

I do wish qsort allowed a void *extra, though.
 
A

Antoninus Twink

Willem said:


Please retain my surname when quoting, Willem - not because I'm precious
about it or anything,

You? Precious about something? Unthinkable.
but simply to disambiguate me from the Riley troll.

Ha! I can't imagine *he'd* be too pleased to be mixed up with *you* ...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,775
Messages
2,569,601
Members
45,182
Latest member
BettinaPol

Latest Threads

Top