2012-07-01 17 views
6

Decir que tengo un conjunto de puntos de datos que se representan como una matriz de matrices de dobles, por loOrdenar una matriz de matrices de diferentes índices en C

double **data; 

Ahora si quería ordenar los datos por parte de la algún campo en cada uno de los puntos de datos, por ejemplo en el campo 2 nd , yo escribiría un comparador que hacer algo como:

int compare_data_second_field(void *a, void *b) { 
    double da = ((double *) a)[1]; 
    double db = ((double *) b)[1]; 
    if (da < db) return -1; 
    else if (da > db) return 1; 
    return 0; 
} 

y luego usar qsort para ordenarlos por la 2 ª fi vejez.

Mi pregunta es ¿cómo generalizo esto si no sé de antemano en qué campo quiero ordenar? Al igual que me gustaría ordenar por el campo 1 st a veces y el campo 5 th a veces, etc. También me gustaría que sea seguro para subprocesos, por lo que no quiero usar una variable global para realizar un seguimiento de lo campo para ordenar por que varios de estos pueden ir a la vez.

En C++ solo usaría una clase de clasificación personalizada y una variable de instancia en la clase para realizar un seguimiento de qué campo ordenar. No sé cómo hacer algo como esto en C.

+6

En realidad está agarrando el tercer elemento. ¿Estás consciente de esto? –

+2

Actualmente es 'doble ** datos;' no 'datos dobles **;' –

+3

Editado para ambos.Si bien son ciertos, son totalmente irrelevantes para la discusión y realmente no agregan nada, pero lo que sea. – pjreddie

Respuesta

7

La mejor manera sería usar qsort_r si está disponible en su plataforma. qsort_r acepta un argumento adicional que se pasa a su comparador, por lo que podría usarlo para pasar el campo por el que desea ordenar sus datos.

Si eso no está disponible en su plataforma, entonces realmente no hay una manera simple de hacer esto. Puede solucionarlo utilizando variables globales, envolviendo sus datos en una estructura que contendría información en el campo de clasificación, o desplegando su propia función tipo qsort_r.

0

Puede declarar un conjunto completo de funciones compare_data_field_N para N = 0,1,2 ... y luego declarar un conjunto compare_data de punteros de función inicializados con las funciones correspondientes. Luego, al qsort en un campo específico, se saca el puntero de función de la matriz para pasar a qsort. Puede utilizar macros para realizar la generación de las funciones y la variedad más simple:

#define REP10(M) M(0) M(1) M(2) M(3) M(4) M(5) M(6) M(7) M(8) M(9) 
#define DECLARE_COMPARE(N)           \ 
    int compare_data_field_##N(void *a, void *b) {     \ 
     double da = ((double *) a)[N];        \ 
     double db = ((double *) b)[N];        \ 
     if (da < db) return -1;         \ 
     else if (da > db) return 1;        \ 
     return 0;             \ 
    } 
#define REF_COMPARE(N) compare_data_field_##N, 

REP10(DECLARE_COMPARE) 
int (*compare_data_field[])(void *, void *) = { REP10(REF_COMPARE) }; 

Solo hay que modificar la macro REP10 si quieres más de 10 campos potenciales.

+0

Quizás estoy equivocado, pero creo que OP quiere elegir el índice del campo para ordenar por _run-time_. –

4

En realidad, hay una solución muy buena para esto con funciones anidadas (que son una extensión de GCC).
Lo que puede hacer es hacer un comparador genérico:

int my_comparator(const void* a, const void* b, int n) 
{ 
    double da = ((double*)a)[n]; 
    double db = ((double*)b)[n]; 
    return (da > db) ? 1 : ((da < db) ? -1 : 0); /* Awesome */ 
} 

y una función de clasificación personalizado que envuelve el original qsort():

void my_qsort(void* base, size_t num, size_t size, 
    int (*comparator)(const void *, const void *, int), int field) 
{ 
    /* Internal comperator */ 
    int my_qsort_comperator(const void* a, const void* b) 
    { 
     return comparator(a, b, field); 
    } 

    /* Invoke the base qsort function */ 
    qsort(base, num, size, my_qsort_comperator); 
} 

Esta función se comporta igual que el original qsort(), salvo que se necesita una argumento adicional field, que indica el índice del campo para ordenar por.

Cuestiones relacionadas