2011-01-02 46 views
19

Como estoy trabajando en la complejidad del tiempo, he estado buscando en la biblioteca de la clase Oracle de Oracle la complejidad temporal de algunos métodos estándar utilizados en las listas, los mapas y las clases. (Más específicamente, ArrayList, HashSet y HashMap)Complejidad del tiempo de los métodos de HashMap

Ahora, cuando se mira en el HashMap javadoc page, en realidad sólo hablan de los métodos get() y put().

los métodos que todavía necesita saber son:

remove(Object o) 
size() 
values() 

creo que remove() será la misma complejidad que get(), O(1), suponiendo que no tienen un HashMap gigante con iguales hashcodes, etc etc. ..

Para size() también me asumir O(1), ya que un HashSet, que también tiene ningún orden, tiene un método size() con la complejidad O(1).

El que no tengo ni idea de es values() - No estoy seguro de si este método se acaba de alguna manera "ejemplar" el HashMap, dando un tiempo de complejidad O(1), o si tendrá que repetir el HashMap, haciendo la complejidad es igual a la cantidad de elementos almacenados en HashMap.

Gracias.

+1

Por cierto, cómo 'values ​​()' da 'O (1)' si es que incluso de alguna manera " copia "HashMap? – Pacerier

+0

por cierto, su enlace está roto – Hengameh

+0

¿Podría mencionar la complejidad exacta (promedio o peor) que está buscando en su pregunta? La complejidad de remove() será diferente en consecuencia, como señaló correctamente @JavaGuy – Dinesh

Respuesta

21

la fuente es a menudo útil: http://kickjava.com/src/java/util/HashMap.java.htm

  • remove: O (1)
  • size: O (1)
  • values: O (n) (en el recorrido a través de iterador)
+7

eliminar ha amortizado la complejidad O (1 + a), donde a depende de cuántos elementos hay en la ranura para la tecla de almohadilla del objeto eliminado – Tim

+0

@Tim, ¿qué es? – Hengameh

+2

@Hengameh a - es un factor de carga. Un factor de carga es una relación entre un número de elementos y el número de ranuras que tiene el mapa hash. Consulte Introducción a los Algoritmos 11.2 Tablas Hash para obtener una explicación más detallada. – Tim

1

Siempre puede echar un vistazo al código fuente y comprobarlo usted mismo.
De todos modos ... Una vez revisé el código fuente y lo que recuerdo es que hay una variable llamada size que siempre contiene el número de elementos en el HashMap así que size() es O(1).

+0

Soy nuevo en Java, así que no tengo idea de los códigos fuente, pero lo probaré. ¡Gracias! – Koeneuze

+0

¿dónde puedo encontrar el código fuente? – Hengameh

5

El código para eliminar (como en rt.jar para HashMap) es:

/** 
* Removes and returns the entry associated with the specified key 
* in the HashMap. Returns null if the HashMap contains no mapping 
* for this key. 
*/ 
final Entry<K,V> removeEntryForKey(Object key) { 
    int hash = (key == null) ? 0 : hash(key.hashCode()); 
    int i = indexFor(hash, table.length); 
    Entry<K,V> prev = table[i]; 
    Entry<K,V> e = prev; 

    while (e != null) { 
     Entry<K,V> next = e.next; 
     Object k; 
     if (e.hash == hash && 
      ((k = e.key) == key || (key != null && key.equals(k)))) { 
      modCount++; 
      size--; 
      if (prev == e) 
       table[i] = next; 
      else 
       prev.next = next; 
      e.recordRemoval(this); 
      return e; 
     } 
     prev = e; 
     e = next; 
    } 

    return e; 
} 

Claramente, el peor de los casos es O (n).

+1

Si bien es técnicamente cierto, esta respuesta podría ser engañosa para algunos. Este código es solo O (n) si todas las claves en HashMap tienen el mismo hashCode, lo cual es poco probable y/o un error. Creo que [el comentario de Tim] (http://stackoverflow.com/questions/4577998/time-complexity-of-hashmap-methods#comment20518366_4578039) es la mejor verdad. –

+1

De acuerdo con @HawkeyeParker, pero el punto sigue siendo válido: runtime = worst case = linear. Nuevamente, esto es improbable y puramente teórico, pero en la forma en que definimos la eficiencia de los algoritmos, la respuesta debe ser lineal porque existe una posibilidad donde O (n) es verdadera. –

1

Buscar: O (1 + k/n)
Insertar: O (1)
Eliminar: O (1 + k/n) donde k es el no. de los elementos de colisión añadidos a la misma lista LinkedList (los elementos k tenían el mismo hashCode)

La inserción es O (1) porque agrega el elemento justo al principio de LinkedList.

Las complejidades de tiempo amortiguado son cerca de O (1) dado un buen hashFunction. Si está demasiado preocupado por el tiempo de búsqueda, intente resolver las colisiones utilizando un BinarySearchTree en lugar de la implementación predeterminada de java ie LinkedList

+0

"La inserción es O (1) porque agrega el elemento a la cabeza de LinkedList". Todavía tiene que pasar por la lista para verificar si ese elemento ya existe al comparar la clave junto con el hash (Ref - código fuente). – Swapnil

+0

mejor usar la búsqueda, poner y quitar :) – Hengameh

Cuestiones relacionadas