2012-09-23 16 views
6

Sto cercando di implementare un semplice comparatore per l'ordinamento degli indici in base ai valori in un array "_vec". Ricevo un messaggio di errore di runtime "operatore < non valido". Non riesco a capire che cosa è sbagliato con il codice seguente:Non valido <asserzione operatore in ordinamento

class Compare{ 
vector<int>& _vec; 
public: 
    Compare(vector<int>& vec) : _vec(vec) {} 
    bool operator()(size_t i, size_t j){ 
     if(_vec[i] != _vec[j]) 
     return _vec[i] < _vec[j]; 
     else 
     return (double)rand()/RAND_MAX < 0.5; 
    } 
}; 

sto usando la seguente funzione di chiamata:

sort(inds.begin(),inds.end(),Compare(vals)); 

dove inds è solo una matrice contenente indici da 1 a 15 (diciamo) e vals è l'array di lunghezza 15 con alcuni valori i cui indici ordinati voglio calcolare. L'obiettivo generale è di randomizzare l'ordinamento quando due (o più) voci in val sono uguali. Qualsiasi aiuto?

+1

È necessario utilizzare caratteri di sottolineatura finali (o qualcos'altro per distinguerli) [anziché i caratteri di sottolineatura iniziali] (http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore -in-ac-identifier). –

+1

@Brian: poiché questi non sono scope del file e il carattere di sottolineatura non è seguito da un carattere maiuscolo, essi sono OK per non essere riservati. Tuttavia, quest'area provoca abbastanza confusione che un'altra convenzione di denominazione potrebbe rendere alcune persone più felici. –

+0

Come nota - se 'vals' ha lunghezza 15, quindi' inds' conviene contenere indici nell'intervallo [0..14], non [1..15]. –

risposta

7

std::sort() aspetta l'operazione di confronto sia stabile - se un determinato risultato viene restituito quando due oggetti vengono confrontate, il confronto deve restituire lo stesso risultato se tali elementi sono confrontati più tardi. Quando restituisci un valore casuale, ovviamente questo non è necessariamente valido.

C++ 03 25.3/4 "Sort e le operazioni correlate" dice:

Se definiamo equiv (a, b) come comp (a, b) & & comp (b, a!), poi i requisiti sono che comp e equiv sia essere relazioni transitive:

  • comp (a, b) & & comp (b, c) implica comp (a, c)
  • equiv (a, b) & & equiv (b, c) implica equiv (a, c)

[Nota: In queste condizioni, si può dimostrare che

  • equiv è una relazione di equivalenza
  • bozzetto induce un pozzo - relazione definita sulle classi di equivalenza determinate da equiv
  • La relazione indotta è un rigoroso ordinamento totale.

-end nota]

E per chiarezza, Tabella 28 definisce una relazione di equivalenza:

== è una relazione di equivalenza, cioè, soddisfa le seguenti proprietà :

  • Per tutti a, a == a.
  • Se a == b, quindi b == a.

Quindi l'operazione Compare() non produrrà una relazione di equivalenza.

È piuttosto piacevole ottenere un'affermazione piuttosto che perdere dati a caso.

Un modo per risolvere il problema di randomizzare l'ordinamento quando due (o più) voci in _vec sono uguali è creare un valore casuale per quegli indici e tenere traccia di quei valori casuali in una mappa dell'indice => valore casuale o qualcosa. Assicurati di tenere traccia di questi valori casuali e utilizzarli in modo tale che le proprietà transitive e di equivalenza di Compare() siano valide.

+0

Grazie Michele. Ora capisco qual è il problema. Sulla base del tuo suggerimento, ho trovato una soluzione: sto passando un vettore di numeri casuali (di lunghezza 15) a Compare() che viene utilizzato per rompere il legame quando i due valori sono uguali. In questo modo le proprietà transitive e di equivalenza di Compare() valgono. – archaic

3

std::sort aspetta il tuo operatore minore di fornire un transitiva rapporto, vale a dire quando il tipo vede A < B è vero e B < C è vero, è implica che A < C è vero pure.

Nell'implementazione, la regola di transitivity non viene mantenuta: quando due elementi sono uguali, si dice casualmente che uno di essi è maggiore dell'altro. Ciò attiva l'asserzione di debug.

Restituisce falso per valori uguali per risolvere questo problema.

+0

Che può essere facilmente implementato usando l'operatore <'per' std :: vector' fornito dalla libreria standatd. – juanchopanza

Problemi correlati