Este es realmente un problema profundo que tiene algunas respuestas metódicas y algunas pragmáticas. Supongo que quiere saber algo sobre los algoritmos disponibles. Si desea saber qué algoritmo funciona mejor en una máquina dada en entradas dadas, continúe y mida los tiempos de ejecución. Si desea comparar la calidad de un compilador para un algoritmo dado, continúe y mida los tiempos de ejecución. Para aprender algo sobre el algoritmo, no lo hagas.
Permítanme primero dar algunas razones por las cuales el uso de tiempos de ejecución no es una buena idea.
- Los
tiempos de ejecución de generalidad medidos usando un idioma y un compilador en una máquina tienen poco significado si cambia algún componente. Incluso las implementaciones ligeramente diferentes del mismo algoritmo pueden funcionar de manera diferente porque se activa una optimización del compilador en el caso, pero no en el otro.
- Predicción
Entonces tiene un par de tiempos de ejecución para algunas entradas. ¿Qué dice eso sobre el tiempo de ejecución de alguna otra entrada? En general, nada.
- Importancia
Por lo general, no comparará todas las entradas (de algún tamaño), de modo que eso restringe inmediatamente su capacidad de comparar algoritmos: ¿tal vez su conjunto de prueba desencadenó el peor caso en uno y el mejor en el otro algoritmo? O tal vez sus entradas fueron demasiado pequeñas para exhibir el comportamiento en tiempo de ejecución .
- Medición
Medición de tiempos de ejecución bien no es trivial. ¿Hay un JIT? ¿Ha habido contención, es decir, estás contando el tiempo que el algoritmo ni siquiera se ejecutó? ¿Puede reproducir exactamente el mismo estado de máquina para otra ejecución (del otro algoritmo), en particular procesos concurrentes y cachés? ¿Cómo se trata la latencia de memoria?
Espero que esto te haya convencido de que los tiempos de ejecución son una medida horrible para comparar algoritmos, y que se necesita algún método general y abstracto para investigar el tiempo de ejecución de algoritmos.
En la segunda parte de la pregunta. ¿Por qué utilizamos comparaciones u operaciones elementales similares?
Tratabilidad analítica
Suponiendo que desee hacer un análisis formal, debe poder hacerlo. Contar declaraciones individuales es muy técnico, a veces incluso difícil; Sin embargo, algunas personas lo hacen (por ejemplo, Knuth). Contar solo algunas declaraciones, aquellas que dominan el tiempo de ejecución, es más fácil. Por la misma razón, a menudo "solo" investigamos (límites superiores en) el peor tiempo de ejecución.
Dominio
La operación seleccionada domina el tiempo de ejecución. Eso no significa que contribuya con la mayor cantidad de tiempo de ejecución; las comparaciones claramente no lo hacen, por ejemplo, en Quicksort al ordenar enteros del tamaño de una palabra. Pero se ejecutan con mayor frecuencia , por lo que al contarlos se cuenta con qué frecuencia se ejecutan las partes más ejecutadas del algoritmo. En consecuencia, su tiempo de ejecución asintótico es proporcional al número de operaciones elementales dominantes. Es por eso que nos sentimos cómodos usando la notación de Landau y la palabra "tiempo de ejecución" aunque solo contamos las comparaciones.
Tenga en cuenta que puede ser útil contar más de una operación. Por ejemplo, algunas variantes de Quicksort toman más comparaciones pero menos intercambios que otras (en promedio).
Para lo que vale, después de haber hecho toda la teoría, es posible que desee volver a visitar los tiempos de ejecución para verificar que las predicciones que hace su teoría sean sólidas. Si no lo son, su teoría no es útil (en la práctica) y debe ampliarse. La jerarquía de memoria es una de las primeras cosas que te das cuenta de que es importante pero que falta en los análisis básicos.