Se presenta C ++ 0x, unordered_setque está disponible en boostmuchos otros lugares. Lo que entiendo es que unordered_setes una tabla hash con O(1)complejidad de búsqueda. Por otro lado, setno es más que un árbol con log(n)complejidad de búsqueda. ¿Por qué demonios usaría alguien en setlugar de unordered_set? es decir, ¿hay una necesidad de setmás?
145

Respuestas:
Cuando, para alguien que quiere iterar sobre los elementos del conjunto, el orden es importante.
fuente
< >?Los conjuntos desordenados tienen que pagar por su tiempo de acceso promedio O (1) de varias maneras:
setusa menos memoria queunordered_setpara almacenar la misma cantidad de elementos.setpueden ser más rápidas que las búsquedas en ununordered_set.unordered_set, a menudo son la garantía de tener mejores peores complejidades de casos deset(por ejemploinsert).setordena los elementos es útil si desea acceder a ellos en orden.sets con<,<=,>y>=.unordered_setNo es necesario que respalden estas operaciones.fuente
<).Siempre que prefiera un árbol a una tabla hash.
Por ejemplo, las tablas hash son "O (n)" en el peor de los casos. O (1) es el caso promedio. Los árboles son "O ( log n)" en el peor de los casos.
fuente
Use set cuando:
Use unordered_set cuando:
Ejemplos:
conjunto:
Entrada: 1, 8, 2, 5, 3, 9
Salida: 1, 2, 3, 5, 8, 9
Conjunto_desordenado:
Entrada: 1, 8, 2, 5, 3, 9
Salida: 9 3 1 8 2 5 (tal vez este orden, influenciado por la función hash)
Principalmente diferencia:
Nota: (en algunos casos
setes más conveniente), por ejemplo, usarvectorcomo claveLa razón por la que
vector<int>puede ser clave essetporque sevectoranulaoperator<.Pero si lo usa
unordered_set<vector<int>>, debe crear una función hashvector<int>, porque el vector no tiene una función hash, por lo que debe definir una como:Puedes ver que en algunos casos
unordered_setes más complicado.Principalmente citado de: https://www.geeksforgeeks.org/set-vs-unordered_set-c-stl/ https://stackoverflow.com/a/29855973/6329006
fuente
Porque std :: set es parte de Standard C ++ y unordered_set no lo es. C ++ 0x NO es un estándar, y tampoco lo es Boost. Para muchos de nosotros, la portabilidad es esencial, y eso significa apegarse al estándar.
fuente
Considere algoritmos de línea de barrido. Estos algoritmos fallarían por completo con las tablas hash, pero funcionan maravillosamente con árboles equilibrados. Para darle un ejemplo concreto de un algoritmo de línea de barrido, considere el algoritmo de la fortuna. http://en.wikipedia.org/wiki/Fortune%27s_algorithm
fuente
Una cosa más, además de lo que otras personas ya mencionaron. Aunque la complejidad amortizado espera para la inserción de un elemento a un unordered_set es O (1), de vez en cuando se va a tomar O (n), ya que las necesidades tabla hash a reestructurarse (el número de necesidades cubos para el cambio) - incluso con una función hash 'buena'. Al igual que insertar un elemento en un vector toma O (n) de vez en cuando porque la matriz subyacente necesita ser reasignada.
Insertar en un conjunto siempre toma como máximo O (log n). Esto podría ser preferible en algunas aplicaciones.
fuente
Disculpe, una cosa más que vale la pena notar sobre la propiedad ordenada:
Si desea un rango de datos en el contenedor, por ejemplo: almacenó el tiempo en el conjunto y desea tiempo del 2013-01-01 al 2014-01-01.
Para un_order_set es imposible.
Por supuesto, este ejemplo sería más convincente para casos de uso entre map y unordered_map .
fuente
g++6.4 stdlibc ++ comparado con el conjunto de referencia desordenadoComparé esta implementación dominante de Linux C ++ para ver la diferencia:
Los detalles y análisis completos de referencia se han proporcionado en: ¿Cuál es la estructura de datos subyacente de un conjunto STL en C ++? y no los repetiré aquí.
"BST" significa "probado con
std::sety" hash map "significa" probado constd::unordered_set. "Heap" es parastd::priority_queuelo que analicé en: Heap vs Binary Search Tree (BST)Como resumen rápido:
el gráfico muestra claramente que, en estas condiciones, la inserción de hashmap siempre fue mucho más rápida cuando hay más de 100 000 elementos, y la diferencia aumenta a medida que aumenta el número de elementos
El costo de este aumento de velocidad es que no puede atravesar eficientemente en orden.
las curvas sugieren claramente que ordenado
std::setestá basado en BST ystd::unordered_setestá basado en hashmap. En la respuesta de referencia, confirmé que mediante el paso GDB depurando el código.Pregunta similar para
mapvsunordered_map: ¿Hay alguna ventaja de usar map sobre unordered_map en caso de claves triviales?fuente
Por supuesto, diría que es conveniente tener cosas en una relación si está buscando convertirlo a un formato diferente.
También es posible que aunque uno sea más rápido para acceder, el tiempo para construir el índice o la memoria utilizada al crearlo y / o acceder a él es mayor.
fuente
Si desea ordenar las cosas, entonces usaría set en lugar de unordered_set. unordered_set se usa sobre el conjunto cuando el pedido almacenado no importa.
fuente
Si bien esta respuesta puede demorar 10 años, vale la pena señalar que
std::unordered_settambién tiene desventajas de seguridad.Si la función hash es predecible (este suele ser el caso a menos que aplique contramedidas como una sal aleatoria), los atacantes pueden crear datos a mano que produzcan colisiones hash y provoquen que todas las inserciones y búsquedas tomen tiempo O (n) .
Esto se puede usar para ataques de denegación de servicio muy eficientes y elegantes.
Muchas (¿la mayoría?) Implementaciones de lenguajes que emplean internamente mapas hash se han encontrado con esto:
fuente