Se presenta C ++ 0x, unordered_set
que está disponible en boost
muchos otros lugares. Lo que entiendo es que unordered_set
es una tabla hash con O(1)
complejidad de búsqueda. Por otro lado, set
no es más que un árbol con log(n)
complejidad de búsqueda. ¿Por qué demonios usaría alguien en set
lugar de unordered_set
? es decir, ¿hay una necesidad de set
má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:
set
usa menos memoria queunordered_set
para almacenar la misma cantidad de elementos.set
pueden 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
).set
ordena los elementos es útil si desea acceder a ellos en orden.set
s con<
,<=
,>
y>=
.unordered_set
No 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
set
es más conveniente), por ejemplo, usarvector
como claveLa razón por la que
vector<int>
puede ser clave esset
porque sevector
anulaoperator<
.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_set
es 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::set
y" hash map "significa" probado constd::unordered_set
. "Heap" es parastd::priority_queue
lo 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::set
está basado en BST ystd::unordered_set
está basado en hashmap. En la respuesta de referencia, confirmé que mediante el paso GDB depurando el código.Pregunta similar para
map
vsunordered_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_set
tambié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