2012-05-14 17 views
5

il mio problema è il seguente (è un esempio semplice per mostrare il problema):ordinare un array in base a membri di un altro array in C++

ho:

int* array1; 
double* array2. 

array1=new int[10]; 
array2=new double[10]; 
array1=filledWithIntegers(random); 
array2=filledWithDoubles(random); 

// Qui voglio ordina array1 in base ai valori dell'array2. Sto cercando di usare la funzione qsort di stdlib. qsort (array1,6, sizeof (int), compare);

Il punto è come rendere la funzione di confronto per ordinare matrice1 basata su matrice2.

Non è possibile utilizzare le strutture di dati della libreria std, deve essere eseguito direttamente nei puntatori degli array.

Grazie.

risposta

5

Invece di smistamento interi di array1, ordinare loro indici utilizzando array2[index] per confrontare articoli, e poi ri-organizzare array1 secondo la permutazione che si ottiene indietro dalla ordinare.

Ecco una quick demo:

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

int array1[] = {1, 7, 3, 9, 5}; 
double array2[] = {1.1, 7.7, 3.3, 9.9, 5.5}; 

int compare (const void * a, const void * b) { 
    double diff = array2[*(int*)a] - array2[*(int*)b]; 
    return (0 < diff) - (diff < 0); 
} 

int main(void) { 
    int perm[5], i; 
    int res[5]; 
    for (i = 0 ; i != 5 ; i++) { 
     perm[i] = i; 
    } 
    qsort (perm, 5, sizeof(int), compare); 
    for (i = 0 ; i != 5 ; i++) { 
     res[i] = array1[perm[i]]; 
    } 
    for (i = 0 ; i != 5 ; i++) { 
     printf("%d\n", res[i]); 
    } 
    return 0; 
} 
+1

Quasi. 'compare' dovrebbe restituire' -1' (invece di '0') quando è più piccolo. – user2k5

+0

@ user2k5 Hai ragione - Ho cambiato la funzione per utilizzare il trucco del segno da [questa risposta] (http://stackoverflow.com/a/4609795/335858). – dasblinkenlight

+0

Non c'è bisogno di un ulteriore array di permutazione, basta calcolare le posizioni di 'a''s e' b' all'interno di 'array1'. Il comparatore deve già sapere 'array2', comunque. –

2

sì. È necessario raggruppare i due array in una matrice di coppia e quindi definire la funzione di confronto.

la funzione di confronto potrebbe essere:

bool compare(const pair<int,double>& t1, const pair<int,double>& t2){ 
    return (t1.second < t2.second); 
} 
+0

Grazie per la risposta. Ho dimenticato di dire che non è una possibilità usare i tipi di libreria std, solo ordinare i valori del puntatore dell'array cercando di preservare il formato dei dati – Pau

+0

quindi potresti definire la mappa tu stesso usando struct? – guinny

+0

Potresti voler dire 'coppia' invece di' mappa'? –

1

Beh, basta utilizzare la posizione degli elementi da indicizzare l'altro di matrice nella funzione confronto (le garanzie standard che gli argomenti puntatore della funzione di confronto sempre puntare nella matrice da ordinare):

int compare(const void *a, const void *b) 
{ 
    unsigned int i = (const int*)a - array1; 
    unsigned int j = (const int*)b - array1; 
    if(array2[i] < array2[j]) 
     return -1; 
    if(array2[i] > array2[j]) 
     return 1; 
    return 0; 
} 

lo svantaggio è che la funzione di confronto deve esplicitamente conoscere gli array specifici, in quanto non può prendere alcun parametro aggiuntivo.

Vorrei mettere in dubbio l'uso di qsort in ogni caso, poiché la tua domanda è codificata in C++. Sebbene lo std::sort abbia lo stesso problema, è possibile raggiungere molto più genericità/astrazione utilizzando un funtore di comparazione che incapsula gli array dipendenti.

+0

grazie per il tempo dedicato a rispondere, ho trovato una soluzione in una precedente. – Pau

Problemi correlati