








Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
ejercicios, evaluacion,. trabajo, colaborativo
Tipo: Guías, Proyectos, Investigaciones
1 / 14
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!









Palabras clave : eficiencia, orden, complejidad, notación.
Complejidad temporal y espacial
Reglas para el cálculo de complejidad
Otras notaciones asintóticas diferentes a la O grande
Notación asintótica y notación O grande
Principales órdenes de complejidad
Toda persona que haya trabajado suficiente tiempo desarrollando programas, se habrá preguntado alguna vez: ¿qué tan demorado será mi programa? ¿Cuál solución será más eficiente, la mía o la de mi amigo? ¿Qué tantos recursos consumirá mi programa? ¿De qué manera depende el consumo de tiempo respecto al tamaño del problema a resolver? ¿Habrá algoritmos más eficientes que el que acabé de desarrollar?
Es conocido que la ejecución de todo algoritmo demanda recursos computacionales, entre estos:
Respecto a un recurso computacional, la complejidad de un algoritmo representa la cantidad del
recurso que el programa demanda para su ejecución. La demanda de procesador se mide por
medio de la complejidad temporal, mientras que la demanda de memoria RAM se mide mediante
la complejidad espacial. No solamente estas dos medidas pueden llevarse a cabo, pero son las más
relevantes y las más usuales. Es mucho más frecuente el análisis de tiempo que el de espacio,
por ello, cuando se encuentren ejemplos en textos y otras fuentes, se debería asumir que se habla
de complejidad temporal, a menos que se indique lo contrario.
En este punto, es muy importante tener claros los conceptos de problema y algoritmo que se propusieron en el módulo de Pensamiento Algorítmico. De la misma forma, se deben conocer los fundamentos y las estructuras de control que fueron cubiertas en el módulo de Programación de Computadores. Le sugiero repasar los puntos que estime podrían necesitar un refuerzo, de esa forma, el tema que aquí se introduce será comprendido con mayor facilidad.
B. Encuentre una función que relacione el tamaño del problema con el número de variables declaradas en el programa. Esta función refleja la complejidad espacial porque entre más variables se declaren, más espacio en memoria RAM requeriría el algoritmo para ejecutarse.
En pocas palabras, la complejidad temporal mide el tiempo empleado y la complejidad espacial mide el espacio requerido.
La notación asintótica es una forma de representación que permite describir la eficiencia de un algoritmo en función de su tasa de crecimiento, es decir, proyecta el comportamiento del algoritmo conforme al aumento del tamaño de sus entradas. El término asintótica se deriva del hecho de que proyecta el comportamiento de cada solución a entradas de gran tamaño. Su uso principal es la comparación de un conjunto de algoritmos para determinar niveles de complejidad.
La notación asintótica O grande (es la letra O del alfabeto, no un cero) se centra en un análisis del peor caso (Cormen, Leiserson, Rivest, & Stein, 2009), es decir, en el escenario más adverso imaginable, que haga que la función ejecute el máximo número de operaciones posible. Puede usarse para describir tanto complejidad temporal como espacial.
En ciencias de la computación y en general en ingeniería, muchas veces se utilizan los conceptos sin traducir del inglés. En este caso particular, algunos textos mostrarán el término Big O a pesar de estar escritos en español. Esta situación es recurrente y por ello el estudiante debería tener una preparación fuerte en el idioma inglés o al menos dominar los términos asociados a su programa de estudio.
Dada una función f(n) se dice que un algoritmo tiene complejidad temporal O(f(n)) si la cantidad de operaciones que ejecuta siempre está por debajo de un múltiplo constante de f(n), para un valor grande de n. Similarmente, se define para la complejidad espacial, pero sobre la cantidad de variables declaradas.
Como es más costoso el recurso de tiempo que el de espacio, resulta más valioso realizar el cálculo de la complejidad temporal, por lo tanto, de aquí en adelante se hará énfasis en él.
El cálculo de la complejidad es un proceso que puede realizarse de forma relativamente sencilla si se atiende al siguiente conjunto de reglas:
A. Para calcular la complejidad temporal de una secuencia de instrucciones en Java como la mostrada en la figura 1, se debe hallar la complejidad de cada instrucción por separado y tomar la más grande de estas.
Figura 1. Representación de un conjunto instrucciones secuenciales Fuente : elaboración propia
B. Para calcular la complejidad temporal de una asignación en Java como la ilustrada en la figura 2, hay que hallar la complejidad del cálculo de la expresión que está siendo asignada.
Figura 2. Representación de una asignación Fuente : elaboración propia
C. Para calcular la complejidad temporal de un condicional en Java como en la figura 3, hay que hallar la complejidad de evaluar la condición de cada instrucción por separado y tomar la más grande de estas.
instrucción 1; instrucción 2; instrucción 3; ... instrucción x;
Variable=expresión;
Existen múltiples órdenes para clasificar la complejidad de los algoritmos; sin embargo, hay un
conjunto de ellos que es más común que los demás. A continuación, se realiza su presentación en
orden creciente, es decir, entre más cerca del final de la lista esté el orden de complejidad, es menos
eficiente respecto a los órdenes que le preceden. Es importante notar la forma en que las reglas
expuestas en el apartado anterior son aplicadas.
Representa la complejidad de un algoritmo que se ejecutará siempre en el mismo tiempo o espacio,
sin importar el tamaño de las entradas. La figura 5 es un ejemplo de un algoritmo con complejidad O(1).
static double calcularArea( double r) { return Math. PI * r * r; }
Figura 5. Método en Java con complejidad de orden constante Fuente : elaboración propia
Representa la complejidad de un algoritmo cuyo tiempo de ejecución se incrementará más lentamente
a medida que el tamaño del conjunto de entradas aumente. La figura 6 es un ejemplo de un algoritmo
que realiza una búsqueda binaria. Como el algoritmo hace divisiones sucesivas de dos para fraccionar
el arreglo, se vuelve comparativamente más eficiente a medida que el tamaño del arreglo aumenta.
static int busquedaBinaria( int arreglo[], int x) { int centro,inferior=0,superior=arreglo.length-1; while (inferior<=superior){ centro=(superior-inferior)/2+inferior; if (arreglo[centro]==x) return centro; else if (x < arreglo[centro]) superior=centro-1; else inferior=centro+1; } return -1; }
Figura 6. Método en Java con complejidad de orden logarítmico Fuente : elaboración propia
Representa la complejidad de un algoritmo que se ejecutará en un tiempo que crecerá linealmente, en proporción directa con el tamaño del conjunto de entradas. Se asume el peor caso, que en la figura 7 consistiría en la ejecución del máximo número de iteraciones posible.
static int busquedaSimple( int arreglo[], int x) { for ( int i=0; i<arreglo.length; i++){ if (x==arreglo[i]) { return i; } } return -1; } Figura 7. Método en Java con complejidad de orden lineal Fuente : elaboración propia
Representa la complejidad de un algoritmo que se ejecutará en un tiempo que crecerá en proporción directa con el cuadrado del tamaño del conjunto de entradas. Como siempre, para la notación O, se asume el peor caso, que en la figura 9 sería la ejecución del máximo número de iteraciones posible.
static boolean busquedaSimpleMatrizCuadrada( int matriz[][], int x) { for ( int i=0; i<matriz.length; i++){ for ( int j=0; j<matriz.length; j++){ if (x==matriz[i][j]) { return true ; } } } return false ; } Figura 9. Método en Java con complejidad de orden cuadrático Fuente : elaboración propia
Representa la complejidad de un algoritmo que se ejecutará en un tiempo que crecerá en un factor
de a con cada adición al conjunto de datos de entrada. Proporción directa con el cuadrado del tamaño
del conjunto de entradas. El ejemplo de la figura 10 representa un algoritmo de complejidad O(2n)
pues cada nueva entrada dobla el tiempo de ejecución.
static int fibonacci( int n) { if (n==1 || n==2) { r eturn 1; } else { return fibonacci (n-1) + fibonacci (n-2); } } Figura 10. Método en Java con complejidad de orden exponencial Fuente : elaboración propia
En muchas situaciones, el peor caso de un algoritmo ocurre solo en situaciones extraordinarias. Tómese por ejemplo un algoritmo cualquiera con complejidad temporal O(n2), que el 99.999% de las veces se comporta como si tuviera complejidad temporal O(n), pero, que en el 0.001% restante alcanza su peor caso y adquiere la complejidad temporal de O(n2). Parece como si se estuviera castigando excesivamente la medida de eficiencia de un algoritmo por algo que ocurrirá con poca probabilidad. Por esta razón, hay otros dos tipos de análisis que se pueden hacer sobre los algoritmos y que son válidos tanto para el tiempo de ejecución como para el espacio en memoria empleado.
La notación asintótica Ω grande (la letra griega Omega), se centra en analizar el mejor caso (Cormen, Leiserson, Rivest, & Stein, 2009), es decir, en el escenario que se ejecuta el mínimo número de operaciones posible. Dada una función f(n) se dice que un algoritmo tiene complejidad temporal Ω (f(n)) si la cantidad de operaciones que ejecuta siempre está por encima de un múltiplo constante de f(n) , para un valor grande de n.
La notación asintótica Θ grande (la letra griega Theta) se usa para describir la tasa de crecimiento en
el mejor y el peor caso del tiempo de ejecución, o el espacio de memoria empleado, de un algoritmo
cuando la tasa es la misma. Dada una función f(n) se dice que un algoritmo tiene complejidad
temporal Θ (f(n)) si y solo si el orden de complejidad en el mejor escenario es Ω (f(n)) y el orden de
complejidad en el peor escenario es O(f(n)).
Referencias
Cormen, T ., L eiserson, C ., Rivest, R., & S tein, C. ( 2009). Introduction to algorithms. Cambridge: The MIT Press.
Sotelo Arévalo, A. (s.f.). Análisis de algoritmos. Bogotá, Colombia.
INFORMACIÓN TÉCNICA
Módulo: Estructura de Datos
Unidad 1: Fundamentos de estructuras de datos
Escenario 2: Análisis de algoritmos
Autor: Javier Fernando Niño Velásquez
Asesor Pedagógico: Heidy Liliana Moncada
Diseñador Gráfico: Nicolás Jiménez O.
Asistente: Ginna Quiroga
Este material pertenece al Politécnico Grancolombiano. Prohibida su reproducción total o parcial.