Los algoritmos de análisis para el rendimiento asintótico están trabajando en las operaciones que deben realizarse y el costo que agregan a la ecuación. Para eso, primero debe saber cuáles son las operaciones realizadas y luego evaluar sus costos.
La búsqueda de una clave en un árbol binario equilibrado (qué mapas son) requiere O(log N)
operaciones complejas. Cada una de esas operaciones implica comparar la clave de una coincidencia y seguir el puntero apropiado (hijo) si la clave no coincide. Esto significa que el costo total es proporcional a log N
veces el costo de esas dos operaciones. Los siguientes punteros son una operación de tiempo constante O(1)
, y las claves de comparación dependen de la clave. Para una clave entera, las comparaciones son rápidas O(1)
. La comparación de dos secuencias es otra historia, se necesita un tiempo proporcional al tamaño de las cadenas involucradas O(L)
(donde he utilizado intencionadamente L
como la longitud de cuerda parámetro en lugar de los más comunes N
.
Al sumar todos los cuesta hasta obtener que el uso de números enteros como claves el costo total es O(log N)*(O(1) + O(1))
que es equivalente a O(log N)
. (O(1)
se oculta en la constante de que la notación O
esconde en silencio.
Si utiliza cadenas como claves, el costo total es O(log N)*(O(L) + O(1))
donde la operación de tiempo constante se oculta n por la operación lineal más costosa O(L)
y se puede convertir en O(L * log N)
. Es decir, el costo de ubicar un elemento en un mapa marcado por cadenas es proporcional al logaritmo de la cantidad de elementos almacenados en el mapa multiplicado por la longitud promedio de las cadenas utilizadas como claves.
Tenga en cuenta que la notación de big-O es la más adecuada para utilizar como herramienta de análisis para determinar cómo se comportará el algoritmo cuando crece el problema, pero oculta muchos hechos importantes para el rendimiento en bruto.
Como el ejemplo más simple, si cambia la clave de una cadena genérica a una matriz de 1000 caracteres, puede ocultar ese costo dentro de la constante eliminada de la notación. La comparación de matrices de 1000 caracteres es una operación constante que simplemente toma bastante tiempo. Con la notación asintótica que sería simplemente una operación O(log N)
, como con enteros.
Lo mismo ocurre con muchos otros costos ocultos, como el costo de creación de los elementos que generalmente se considera como una operación de tiempo constante, simplemente porque no depende de los parámetros de su problema (el costo de ubicar el bloque de memoria en cada asignación no depende de su conjunto de datos, sino de la fragmentación de la memoria que está fuera del alcance del análisis de algoritmo, el costo de adquirir el bloqueo dentro de malloc para garantizar que no dos procesos intentan devolver el mismo bloque de memoria depende de la contención del bloqueo que depende del número de procesadores, procesos y la cantidad de solicitudes de memoria que realizan ..., nuevamente fuera del alcance del análisis del algoritmo). Al leer los costos en la notación de la gran O, debes ser consciente de lo que realmente significa.
Bastante fácil de escribir una pequeña prueba usted mismo, pensé. Sin embargo, los enteros siempre serán al menos tan rápidos como las cadenas y probablemente mucho más rápidos. –
Siguiente pregunta: si cambia un mapa para tomar notas en lugar de cadenas, ¿cuánto rendimiento va a perder haciendo las conversiones usted mismo? –
@David: depende de muchas cosas, pero puede ser bastante. El costo agregado es 'O (L)' (L: tamaño de la cadena) para cada operación de inserción y búsqueda, pero se realiza solo una vez para toda la operación: 'O (L) + O (log N)' que será o bien 'O (L)' o 'O (log N)' lo que sea mayor. Si las claves se mantienen como cadenas, entonces la comparación se realiza en todos los nodos, y el costo es 'O (L) * O (log N)' que es 'O (L * log N)' –