Usando C ++, y con suerte la biblioteca estándar, quiero ordenar una secuencia de muestras en orden ascendente, pero también quiero recordar los índices originales de las nuevas muestras.
Por ejemplo, tengo un conjunto, o vector, o matriz de muestras A : [5, 2, 1, 4, 3]
. Quiero ordenarlos para que sean B : [1,2,3,4,5]
, pero también quiero recordar los índices originales de los valores, para poder obtener otro conjunto que sería:
C : [2, 1, 4, 3, 0 ]
- que corresponde al índice de cada elemento en 'B', en el original ' UNA'.
Por ejemplo, en Matlab puedes hacer:
[a,b]=sort([5, 8, 7])
a = 5 7 8
b = 1 3 2
¿Alguien puede ver una buena manera de hacer esto?
for (size_t i = 0; i != idx.size(); ++i) idx[i] = i;
prefiero el estándarstd::iota( idx.begin(), idx.end(), 0 );
#include <numeric>
for iota ()iota
es el algoritmo menos obvio en toda la biblioteca estándar de C ++.Puede ordenar std :: pair en lugar de solo ints: el primer int son datos originales, el segundo int es el índice original. Luego, proporcione un comparador que solo se clasifique en el primer int. Ejemplo:
Ordene la nueva instancia del problema utilizando un comparador como:
El resultado de std :: sort en v_prime, usando ese comparador, debería ser:
Puede despegar los índices recorriendo el vector, tomando .second de cada std :: pair.
fuente
Supongamos que el vector dado es
Crea un nuevo vector
Ordene V y mientras ordena en lugar de comparar elementos de V, compare los elementos correspondientes de A
fuente
std::iota()
para una inicialización de elegentPackage másmap
Escribí una versión genérica de clasificación de índice.
El uso es el mismo que el de std :: sort excepto para un contenedor de índice para recibir índices ordenados. pruebas:
debería obtener 2 1 0 3. para los compiladores sin soporte de c ++ 0x, reemplace la expresión lamba como plantilla de clase:
y reescribir std :: ordenar como
fuente
Ahora
a
contiene tanto nuestros valores como sus respectivos índices en el ordenado.a[i].first = value
ai
'th.a[i].second = idx
en la matriz inicialfuente
Me encontré con esta pregunta, y descubrí que ordenar los iteradores directamente sería una forma de ordenar los valores y realizar un seguimiento de los índices; No es necesario definir un contenedor adicional de
pair
s de (valor, índice) que es útil cuando los valores son objetos grandes; Los iteradores proporcionan acceso tanto al valor como al índice:en cuanto al ejemplo de uso:
ahora, por ejemplo, el quinto elemento más pequeño en el vector ordenado tendría valor
**idx[ 5 ]
y su índice en el vector original seríadistance( A.begin( ), *idx[ 5 ] )
o simplemente*idx[ 5 ] - A.begin( )
.fuente
Hay otra forma de resolver esto, usando un mapa:
Sin embargo, esto erradicará elementos no únicos. Si eso no es aceptable, use un mapa múltiple:
Para generar los índices, itere sobre el mapa o el mapa múltiple:
fuente
Hermosa solución por @Lukasz Wiklendt! Aunque en mi caso necesitaba algo más genérico, lo modifiqué un poco:
Ejemplo: Encuentre índices ordenando un vector de cadenas por longitud, excepto por el primer elemento que es un ficticio.
huellas dactilares:
fuente
Considere usar
std::multimap
según lo sugerido por @Ulrich Eckhardt. Solo que el código podría hacerse aún más simple.Dado
Ordenar en el tiempo medio de inserción
Para recuperar valores e índices originales
La razón para preferir a
std::multimap
a astd::map
es permitir valores iguales en vectores originales. También tenga en cuenta que, a diferencia de forstd::map
,operator[]
no está definido parastd::multimap
.fuente
Hacer una
std::pair
función in y luego ordene el par:Versión genérica :
ideona
fuente
¿Son únicos los elementos del vector? Si es así, copie el vector, ordene una de las copias con STL Ordenar luego puede encontrar qué índice tenía cada elemento en el vector original.
Si se supone que el vector maneja elementos duplicados, creo que es mejor implementar su propia rutina de clasificación.
fuente
Bueno, mi solución usa la técnica de residuos. Podemos colocar los valores bajo ordenación en los 2 bytes superiores y los índices de los elementos, en los 2 bytes inferiores:
Luego ordena la matriz
myints
como de costumbre:Después de eso, puede acceder a los índices de los elementos a través de residuum. El siguiente código imprime los índices de los valores ordenados en orden ascendente:
Por supuesto, esta técnica funciona solo para los valores relativamente pequeños en la matriz original
myints
(es decir, aquellos que pueden caber en los 2 bytes superiores deint
). Pero tiene el beneficio adicional de distinguir valores idénticos demyints
: sus índices se imprimirán en el orden correcto.fuente
Si es posible, puede construir la matriz de posición utilizando la función de búsqueda y luego ordenar la matriz.
O tal vez pueda usar un mapa donde la clave sería el elemento, y los valores una lista de su posición en las siguientes matrices (A, B y C)
Depende de los usos posteriores de esas matrices.
fuente
Para este tipo de pregunta Almacene los datos del conjunto original en un nuevo dato y luego binario busque el primer elemento del conjunto ordenado en el conjunto duplicado y ese índice debe almacenarse en un vector o conjunto.
Aquí binarysearch es una función que toma la matriz, el tamaño de la matriz, el elemento de búsqueda y devolvería la posición del elemento buscado
fuente
Hay muchas maneras. Una solución bastante simple es usar un vector 2D.
Aquí está la salida:
fuente