2011-05-20 14 views
6

Estoy tratando de ordenar una matriz A cuyos elementos son índices. Los índices se refieren a otra matriz B cuyo valor determinará el orden de A. Por lo tanto, me gustaría ordenar A de manera que B[ A[i] ] va en aumento.Ordenar una matriz C en función del contenido de otra matriz

Por ejemplo:

 
A = [0, 1, 4, 5, 7] 
B = [5, 3, 8, 2, 2, 7, 1, 6, 3, 9] 

Ordenado A habría

 
A' = [ 7, 4, 1, 0, 5 ] 

es esto posible con la de C incorporado de tipo, o voy a tener que escribir mi propia aplicación?

EDITAR: Estas matrices son variables de funciones locales.

+0

Habrá hacks feos que pueden hacer que esto funcione con qsort, pero creo que es mejor que escribas tu propia versión ... –

+1

@Pavan Preferiría luchar contra zombies en el desierto en lugar de usar mi propio procedimiento de clasificación en producción. – cnicutar

+0

No es un hack feo. Es simplemente que hay una función que mapea el valor de la matriz al orden de clasificación. En este caso, la función puede ser immplementada por una búsqueda de matriz, pero no es un requisito inusual. –

Respuesta

6

Si desea utilizar qsort, lo mejor que puede-do sería volver a envolver los índices en A y los valores en B en una estructura, y luego hacer un comparador basado en una nueva matriz que struct. Por ejemplo:

typedef struct 
{ 
    int index_from_A; 
    int value_from_B; 
} index_value_wrapper; 

index_value_wrapper index_wrapper_array[5]; 

for (int i=0; i < 5; i++) 
{ 
    index_wrapper_array[i].index_from_A = A[i]; 
    index_wrapper_array[i].value_from_B = B[A[i]]; 
} 

int comparitor (const void* lhs, const void* rhs) 
{ 
    return (lhs.value_from_B - rhs.value_from_B); 
} 

Ahora se puede ejecutar qsort en la matriz de estructura y desde allí se puede extraer la secuencia ordenada adecuada que se desee para la matriz original A sin tener que utilizar una función de clasificación personalizado.

3

Creo que se puede utilizar qsort y un comparador de encargo

int comparator(const void *x, const void *y) 
{ 
    return (b[*(int*)x] - b[*(int*)y]); 
} 
+0

¿Hay alguna manera de pasar las referencias de matriz al comparador? – ajwood

+0

@ajwood No estoy seguro de entender su pregunta – cnicutar

+0

Ajwood, si se refiere a los índices de matriz, no - los elementos de la matriz se mueven a medida que avanza la clasificación –

4

Si lo tienes disponible, qsort_r proporciona una manera de hacer esto. Puede darle información de contexto en un parámetro adicional. Ese contexto se pasa a la función de comparación. Puede acceder a esa información adicional para extraer la información de clasificación deseada.

El compilador Microsoft tiene una análoga: qsort_s

+0

Estoy usando Ubuntu y no parece estar cerca ... – ajwood

2

Use su regla como la función de comparación de qsort (siempre y cuando B es mayor que A):

#include <stdio.h> 
#include <stdlib.h> 

int A[] = {0, 1, 4, 5, 7}; 
int B[]= {5, 3, 8, 2, 2, 7, 1, 6, 3, 9}; 

int my_cmp(const void *a_, const void *b_,void *arg_) 
{ 
    const int *a = a_, *b = b_; 

    if(B[*a] == B[*b]) 
     return 0; 
    else if (B[*a] < B[*b]) 
     return -1; 
    else 
     return 1; 

} 

int main(int argc,char *arga[]) 
{ 
    int i; 

    qsort(A,sizeof A/sizeof A[0] ,sizeof A[0],my_cmp); 

    puts("Sorted A"); 
    for(i = 0 ; i < sizeof A/sizeof A[0]; i++) { 
     printf("A[%d] : %d B[A[%d]] : %d\n",i,A[i],i,B[A[i]]); 
    } 

    return 0; 
} 

Esto da:

$ ./a.out 
Sorted A 
A[0] : 4 B[A[0]] : 2 
A[1] : 1 B[A[1]] : 3 
A[2] : 0 B[A[2]] : 5 
A[3] : 7 B[A[3]] : 6 
A[4] : 5 B[A[4]] : 7 

Disponible en muchas plataformas también es qsort_r (en Linux tendrá que #define _GNU_SOURCE antes de incluir <stdlib.h> para usarlo. g que cambiaría la función de comparación, por ejemplo,

int my_cmp(const void *a_, const void *b_,void *arg_) 
{ 
    const int *a = a_, *b = b_, *arg = arg_; 

    if(arg[*a] == arg[*b]) 
     return 0; 
    else if (arg[*a] < arg[*b]) 
     return -1; 
    else 
     return 1; 

} 

Y llama qsort_r como

qsort_r(A,sizeof A/sizeof A[0] ,sizeof A[0],my_cmp,B); 
+0

No funciona si A y B son locales a main. –

+0

Esto funciona bien siempre que no sea de subprocesos múltiples. Si no es de subproceso único y los datos de referencia (B) no son estáticos, entonces no funcionarían. –

+0

@Paul qsort es la única función de clasificación estándar en C y funciona de esa manera; de lo contrario, tendrá que hacer las suyas propias, o usar algo no estándar, como qsort_r - agregó un ejemplo para eso. A menos que esté en un entorno multiproceso, A y B pueden ser locales. Solo tiene que establecer un 'int *' global en su matriz B antes de llamar a qsort – nos

1

Cree otra matriz C del tipo struct { int a_value; int b_value}, inicialice cada elemento con los valores de cada índice de ay el valor buscado desde b. Ordenar eso, recorra el C ordenado copiando los valores a a A.

Viola. No, es un gran violín. Voila!

Cuestiones relacionadas