Tengo un vector de dobles. Quiero ordenarlo de mayor a menor, y obtener los índices de los elementos K superiores. std :: sort simplemente se ordena y no devuelve los índices que creo. ¿Cuál sería una forma rápida de obtener los mejores índices K de los elementos más grandes?¿cómo puedo ordenar una lista y obtener los mejores elementos K? (STL)
Respuesta
La primera cosa que viene a la mente es un poco hacker, pero se podría definir una estructura que almacena tanto el doble y su índice original, entonces sobrecargar el operador < para ordenar en base al doble:
struct s {
double d;
int index;
bool operator < (const struct &s) const {
return d < s.d;
}
};
Entonces podrías recuperar los índices originales de la estructura.
ejemplo Fuller:
vector<double> orig;
vector<s> v;
...
for (int i=0; i < orig.size(); ++i) {
s s_temp;
s_temp.d = orig[i];
s_temp.index = i;
v.push_back(s);
}
sort(v.begin(), v.end());
//now just retrieve v[i].index
Esto dejarlos ordenados de menor a mayor, pero que podría sobrecargar el operador> lugar y luego pasar en mayor a la función de clasificación si se desea.
-1: demasiado lento para la cosa, que desea ....... –
nth_element como sugirió que no funcionaría si los N superiores necesitaran ordenarse ellos mismos; partial_sort sería significativamente más rápido si K fuera bastante pequeño y n bastante grande - n log (K) en oposición a n log (n); pero puede usar partial_sort en su lugar si necesita el rendimiento, pero deberá sobrecargar el operador> y ordenarlo de mayor a menor (partial_sort ordena la parte superior de los elementos, no la parte inferior) – user470379
Sí, usted estas en lo correcto. Pero cuando no tienes ninguna expectativa sobre K y N (no sé cuánto K será más pequeño que N), es mejor usar ordenación parcial (creo); podría ser más rápido en 50% de los casos, pero todavía es una pérdida de tiempo menor. Y solo un comentario: no es necesario sobrecargar al operador> para hacer lo opuesto y hacerlo parecer complicado, si es necesario. Simplemente podría pasar una función, definida por usted, a partial_sort. Por ejemplo: 'partial_sort (myvector.begin(), myvector.begin() + 5, myvector.end(), myfunction);' Es similar con nth_element, también. –
No estoy seguro acerca de los algoritmos pre-enlatados, pero eche un vistazo a selection algorithms; si necesita los elementos K superiores de un conjunto de valores N y N es mucho mayor que K, existen métodos mucho más eficientes.
Si se puede crear una clase de indexación (como respuesta de @ user470379 - básicamente una clase que encapsula un puntero/índice para los datos "reales", que es de sólo lectura), a continuación, utilizar una cola de prioridad de tamaño máximo de K, y agregue cada elemento sin clasificar a la cola de prioridad, saltando del elemento inferior cuando la cola alcance el tamaño K + 1. En casos como N = 10 , K = 100, esto maneja casos de manera mucho más simple y eficiente que una clasificación completa.
OK, ¿qué tal esto?
bool isSmaller (std::pair<double, int> x, std::pair<double, int> y)
{
return x.first< y.first;
}
int main()
{
//...
//you have your vector<double> here, say name is d;
std::vector<std::pair<double, int> > newVec(d.size());
for(int i = 0; i < newVec.size(); ++i)
{
newVec[i].first = d[i];
newVec[i].second = i; //store the initial index
}
std::sort(newVec.begin(), newVec.end(), &isSmaller);
//now you can iterate through first k elements and the second components will be the initial indices
}
Uso multimap
para vector
's (valor de índice) para manejar los DUP. Use iteradores inversos para recorrer los resultados en orden descendente.
#include <multimap>
#include <vector>
using namespace std;
multimap<double, size_t> indices;
vector<double> values;
values.push_back(1.0);
values.push_back(2.0);
values.push_back(3.0);
values.push_back(4.0);
size_t i = 0;
for(vector<double>::const_iterator iter = values.begin();
iter != values.end(); ++iter, ++i)
{
indices.insert(make_pair<double,int>(*iter, i));
}
i = 0;
size_t limit = 2;
for (multimap<double, size_t>::const_reverse_iterator iter = indices.rbegin();
iter != indices.rend() && i < limit; ++iter, ++i)
{
cout << "Value " << iter->first << " index " << iter->second << endl;
}
salida es
calidad-precio 4 Índice 3
Valor 3 Índice 2
Si sólo desea los vector
índices después de clase, utilice esto:
#include <algorithm>
#include <vector>
using namespace std;
vector<double> values;
values.push_back(1.0);
values.push_back(2.0);
values.push_back(3.0);
values.push_back(4.0);
sort(values.rbegin(), values.rend());
Las principales entradas K están indexadas por 0 a K-1, y aparecen en orden descendente. Esto utiliza iteradores inversa combinados con el estándar sort
(usando less<double>
para lograr orden descendente cuando iterado adelante Equivalentemente:.
sort(values.rbegin(), values.rend(), less<double>());
Código de ejemplo para la solución excelente nth_element
sugerido por @Kiril aquí (K = 125 000, N = 500.000). Quería probar esto, así que aquí está.
vector<double> values;
for (size_t i = 0; i < 500000; ++i)
{
values.push_back(rand());
}
nth_element(values.begin(), values.begin()+375000, values.end());
sort(values.begin()+375000, values.end());
vector<double> results(values.rbegin(), values.rbegin() + values.size() - 375000);
se puede utilizar el algoritmo de nth_element
STL - esto le devolverá los mayores N elementos (esta es la manera más rápida, utilizando STL) y luego usar .Sort en ellos, o puede utilizar el algoritmo partial_sort, si desea que los primeros elementos de K a ser clasificadas (:
Utilizando sólo .Sort es horrible - es muy lenta con el fin de que deseas .. .Sort es grande algoritmo de STL, pero para la clasificación de todo el contenedor, no sólo los primeros elementos (K, no es un accidente, el existung de nth_element y partial_sort;)
+1 para encontrar nth_element. (Por favor, enlace a documentos oficiales, aunque) –
http://cplusplus.com/reference/algorithm/nth_element, allí se puede encontrar el partial_sort, también –
@ Jason: ¿Dónde se encuentra "documentos oficiales" en línea para enlazar a? – GManNickG
Entonces realmente necesitas una estructura que asigne índices a los dobles correspondientes.
Puede usar la clase std::multimap
para realizar esta asignación. Como Jason ha notado std::map
no permite llaves duplicadas.
std::vector<double> v; // assume it is populated already
std::multimap<double, int> m;
for (int i = 0; i < v.size(); ++i)
m.insert(std::make_pair(v[i], i));
...
Después de haber hecho esto usted podría iterar sobre primeros diez elementos como mapa conserva clasificación de llaves de los elementos.
esto no funciona si hay duplicados. –
- 1. Cómo obtener los primeros 10 elementos ordenados de una lista sin ordenar toda la lista
- 2. ¿Cómo ordenar un vector STL?
- 3. ¿Cómo puedo ordenar un mapa STL por valor?
- 4. Ordenar la lista utilizando la función STL tipo
- 5. ¿Cómo puedo ordenar parcialmente una lista de Python?
- 6. ¿Cómo puedo recortar todos los elementos en una lista?
- 7. Obtener elementos distintos de una lista
- 8. ¿Cómo puedo permitir que un usuario vuelva a ordenar elementos de una lista?
- 9. ¿Cómo ordenar una lista numéricamente?
- 10. ¿Cómo almaceno arreglos en una lista STL?
- 11. Obtener una lista de elementos distintos y su recuento de
- 12. Obtener los n elementos menores de una lista en Python
- 13. Ordenar una lista de tuplas en función de dos elementos
- 14. ¿Cómo ordenar una lista según otra lista?
- 15. ¿Cómo puedo filtrar solo los elementos de una lista que se encuentra en una posición pareja?
- 16. ¿Cómo puedo ordenar la lista genérica DESC y ASC?
- 17. ¿Cómo puedo ordenar una lista vinculada en sql?
- 18. ¿Cómo ordenar elementos en ToolStripItemCollection?
- 19. ¿Cómo puedo obtener todos los elementos secundarios de los elementos con selectores CSS que usan selenio?
- 20. ¿Cómo puedo ordenar un conjunto en una lista en Java?
- 21. ¿Cómo puedo obtener una lista de colores visualmente distintos?
- 22. Ordenar una lista de tuplas por sus segundos elementos
- 23. ¿Anida los elementos de la lista dentro de los elementos de lista de una lista ordenada?
- 24. Generar todos los subconjuntos de tamaño k (que contienen elementos k) en Python
- 25. Ordenar en una lista
- 26. Python - Cómo extraer los últimos x elementos de una lista
- 27. ¿Cómo puedo obtener un primer elemento de una lista ordenada?
- 28. ¿Dónde puedo obtener una lista de todos los elementos de iOS?
- 29. todos los elementos en una lista
- 30. ¿Cómo escribir una lista vacía usando los combinadores S, K y I?
¿No serían 0, 1, 2, 3, 4, 5, 6, 7, 8 y 9? – wheaties
Después de la clasificación, los primeros elementos K (o los últimos elementos K) serían los elementos superiores. – Kendrick
después de la ordenación, sí, pero al parecer a kop le gustaría encontrar los índices en el rango original, antes del género. – flownt