2012-09-23 14 views
6

Estoy tratando de implementar un comparador simple para ordenar los índices basado en los valores de una matriz "_vec". Recibo un mensaje de error de "operador < sin validez". No entiendo lo que está mal con el siguiente código:Invalid <aserción del operador en el género

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; 
    } 
}; 

estoy usando la siguiente función llamada:

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

donde inds es sólo una matriz que contiene los índices de 1 a 15 (por ejemplo) y vals es la matriz de longitud 15 con algunos valores cuyos índices ordenados quiero calcular. El objetivo general es aleatorizar el orden de clasificación cuando dos (o más) entradas en vals son iguales. ¿Alguna ayuda?

+1

Debe usar guiones bajos finales (u otra cosa para distinguirlos) [en lugar de guiones bajos] (http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-un-underscore -in-ac-identificador). –

+1

@Brian: dado que estos no son el alcance del archivo y el guión bajo no es seguido por un carácter en mayúscula, están bien para no ser reservados. Aún así, esta área causa suficiente confusión como para que otra convención de nombres pueda hacer que algunas personas sean más felices. –

+0

Como nota: si 'vals' tiene longitud 15, entonces' inds' debería contener índices en el rango [0..14], no [1..15]. –

Respuesta

7

std::sort() espera que la operación de comparación sea estable: si se devuelve un resultado particular cuando se comparan dos elementos, la comparación debe devolver el mismo resultado si se vuelven a comparar. Cuando devuelves un valor aleatorio, obviamente no necesariamente se mantendrá.

C++ 03 25.3/4 "Ordenar y las operaciones conexas", dice:

Si definimos equiv (a, b) como un borrador (a, b) & & borrador (b, a!), entonces las requisitos son que los y equiv ser ambos relaciones transitivos:

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

[Nota: En estas condiciones, se puede demostrar que

  • equiv es una relación de equivalencia
  • los induce un pozo -relación definida en las clases de equivalencia determinadas por el equivalente
  • La relación inducida es un ordenamiento total estricto.

nota -end]

Y de aclaración, la Tabla 28 define una relación de equivalencia:

== es una relación de equivalencia, es decir, satisface las siguientes propiedades:

  • Para todos a, a == a.
  • Si a == b, entonces b == a.

Por lo que su operación Compare() no producirá una relación de equivalencia.

Es agradable obtener una afirmación en lugar de perder datos aleatoriamente.

Una forma de resolver el problema de aleatorizar el orden cuando dos (o más) entradas en _vec son iguales es crear un valor aleatorio para esos índices y realizar un seguimiento de esos valores aleatorios en un mapa de índice => valor aleatorio o algo así. Solo asegúrese de hacer un seguimiento y usar esos valores aleatorios de tal forma que se mantengan las propiedades de transitiva y equivalencia de Compare().

+0

Gracias Michael. Ahora entiendo cuál es el problema. En función de su sugerencia, encontré una solución: ahora estoy pasando un vector de números aleatorios (de longitud 15) a Comparar() que se utiliza para romper el empate cuando los dos valores son iguales. De esta manera, se mantienen las propiedades transitivas y de equivalencia de Compare(). – archaic

3

std::sort espera que el operador menor que para el suministro de un relación transitiva, es decir, cuando el género ve A < B es verdadera y B < C es cierto, implica que A < C es cierto también.

En su implementación, la regla de transitividad no se cumple: cuando dos elementos son iguales, usted indica aleatoriamente el orden en que uno de ellos es mayor que el otro. Esto desencadena la afirmación de depuración.

Devuelve falso para valores iguales para solucionar esto.

+0

que se puede implementar fácilmente utilizando el 'operador <' para 'std :: vector' proporcionado por la biblioteca standatd. – juanchopanza