67

1.1 Concepto de Complejidad de Algoritmos. 1.2 Aritmética de la notación O. 1.3 Complejidad. 1.3.1 Tiempo de ejecución de un algoritmo. 1.3.2 Complejidad

Embed Size (px)

Citation preview

1.1 Concepto de Complejidad de Algoritmos.

1.2 Aritmética de la notación O.

1.3 Complejidad.

1.3.1 Tiempo de ejecución de un algoritmo.

1.3.2 Complejidad en espacio.

1.4 Selección de un algoritmo.

Unidad 1.- Análisis de algoritmos.

Los datos a procesar por una computadora se clasifican en :

a) Simples

b) Estructurados

Introducción a la materia

a) Datos Simples:

La principal característica de los datos simples es que ocupan sólo una casilla de memoria, por lo tanto una variable simple hace referencia a un único valor a la vez.

Dentro de este grupo de datos se encuentran: enteros, reales, caracteres, booleanos, enumerados y subrangos ( los dos últimos no existen en algunos lenguajes de programación.

TIPOS DE DATOS SIMPLES• Es uno de los conceptos fundamentales de cualquier

lenguaje de programación. Estos definen los métodos de almacenamiento disponibles para representar información, junto con la manera en que dicha información ha de ser interpretada.

• Para crear una variable (de un tipo simple) en memoria debe declararse indicando su tipo de variable y su identificador que la identificará de forma única..

• Los simples son tipos nucleares que no se derivan de otros tipos, como los enteros, de coma flotante, booleanos y de carácter.

Definición de bitUnidad mínima de información digital que puede ser tratada por una computadora. Proviene de la contracción de la expresión binary digit (dígito binario), y puede tener dos estados "0" o "1".

Definición de byteSimboliza un carácter en una computadora (ej. una letra). . Conjunto significativo de ocho bits que representan un carácter, por ejemplo la letra "a", en un sistema informático.

Definición de carácterCualquier signo tipográfico. Puede ser una letra, un número, un signo de puntuación o un espacio.

Definición de asciiAmerican Standard Code for Information Interchange. Estándar Americano para Intercambio de Información. La tabla básica de caracteres ASCII está compuesta por 128 caracteres incluyendo símbolos y caracteres de control. Existe una versión extendida de 256. Conjunto de normas de codificación de caracteres mediante caracteres numéricos, de amplia utilización en informática y telecomunicaciones.

b) Dato Estructurado o Abstracto:

Los datos estructurados se caracterizan por el hecho de que con un nombre (identificador de variable estructurada) se hace referencia a un grupo de casillas de memoria. Es decir, un dato estructurado tiene varios componentes. Cada uno de los componentes básicos puede ser a su vez un dato simple o estructurado. Sin embargo, los componentes básicos (los de nivel más bajo) de cualquier tipo estructurado son datos simples. Se ejemplifica un dato estructurado en la siguiente figura :

Las estructuras de datos constituyen un aspecto muy importante de la computación. Muchos algoritmos, requieren una representación apropiada de los datos para lograr ser eficientes. Esta representación junto con las operaciones permitidas se llama estructura de datos.

Definición de Estructura de datos:Es una colección de datos organizados de un modo particular

Unidad 1 - Análisis De Algoritmos

Tipos de algoritmos según su función

• Algoritmo de ordenamiento

Es un algoritmo que pone elementos de una lista o un vector en una secuencia dada por una relación de orden, es decir, el resultado de salida ha de ser una permutación —o reordenamiento— de la entrada que satisfaga la relación de orden dada.

• Algoritmo de búsqueda

Es aquel que está diseñado para localizar un elemento concreto dentro de una estructura de datos. Consiste en solucionar un problema booleano de existencia o no de un elemento determinado en un conjunto finito de elementos, es decir al finalizar el algoritmo este debe decir si el elemento en cuestión existe o no en ese conjunto (si pertenece o no a él), además, en caso de existir, el algoritmo podría proporcionar la localización del elemento dentro del conjunto.

Concepto de complejidad de algoritmos

• Algoritmo: Es una secuencia de operaciones o pasos perfectamente definidos que conducen a la solución de un problema

• Complejidad de un algoritmo: es la función que da la eficiencia de un algoritmo (tiempo de respuesta)

Concepto de complejidad de algoritmos

Dado el nombre queremos conocer su numero de teléfono.

• Búsqueda secuencial: Recorre cada elemento, uno a uno, hasta encontrar el nombre buscado y su teléfono

• Búsqueda binaria: compara el nombre buscado con el que se encuentra en la mitad de la lista. Divide la lista en dos partes y determina en cual de las dos se encuentra el nombre buscado

Es evidente que entre menos comparaciones se realicen menos tiempo de ejecución tendrá el algoritmo

Concepto Complejidad Algoritmos

La resolución práctica de un problema exige por una parte un algoritmo o método de resolución y por otra un programa o codificación de aquel en un ordenador real.

Ambos componentes tienen su importancia, pero la del algoritmo es absolutamente esencial, mientras que la codificación puede muchas veces pasar a nivel de anécdota. A efectos prácticos o ingenieriles, nos deben preocupar los recursos físicos necesarios para que un programa se ejecute. Aunque puede haber muchos parámetros, los mas usuales son el tiempo de ejecución y la cantidad de memoria (espacio).

Ocurre con frecuencia que ambos parámetros están fijados por otras razones y se plantea la pregunta inversa: ¿cual es el tamaño del mayor problema que puedo resolver en T segundos y/o con M bytes de memoria?

En lo que sigue nos centramos casi siempre en el parámetro tiempo de ejecución, si bien las ideas desarrolladas son fácilmente aplicables a otro tipo de recursos.

Para cada problema determinaremos una medida N de su tamaño (por número de datos) e intentaremos hallar respuestas en función de dicho N.

El concepto exacto que mide N depende de la naturaleza del problema.

Así, para un vector se suele utizar como N su longitud; para una matriz, el número de elementos que la componen; para un grafo, puede ser el número de nodos (a veces es mas importante considerar el número de arcos, dependiendo del tipo de problema a resolver), en un archivo se suele usar el número de registros, etc.

Es imposible dar una regla general, pues cada problema tiene su propia lógica de coste.

Concepto Complejidad Algoritmos

Tiempo de Ejecución Una medida que suele ser útil conocer es el tiempo de ejecución de un programa en función de N, lo que denominaremos T(N).

Esta función se puede medir físicamente (ejecutando el programa, reloj en mano), o calcularse sobre el código contando instrucciones a ejecutar y multiplicando por el tiempo requerido por cada instrucción.

Así, un trozo sencillo de programa como: S1; for (int i= 0; i < N; i++) S2; requiere T(N)= t1 + t2*N siendo t1 el tiempo que lleve ejecutar la serie “S1” de sentencias, y t2 el que lleve la serie “S2”.

Prácticamente todos los programas reales incluyen alguna sentencia condicional, haciendo que las sentencias efectivamente ejecutadas dependan de los datos concretos que se le presenten.

Concepto Complejidad Algoritmos

Esto hace que mas que un valor T(N) debamos hablar de un rango de valores Tmin(N) T(N) Tmax(N) ⇐ ⇐los extremos son habitualmente conocidos como “caso peor” y “caso mejor”.

Entre ambos se hallara algún “caso promedio” o más frecuente.

Cualquier fórmula T(N) incluye referencias al parámetro N y a una serie de constantes “Ti” que dependen de factores externos al algoritmo como pueden ser la calidad del código generado por el compilador y la velocidad de ejecución de instrucciones del ordenador que lo ejecuta.

Dado que es fácil cambiar de compilador y que la potencia de los ordenadores crece a un ritmo vertiginoso (en la actualidad, se duplica anualmente), intentaremos analizar los algoritmos con algún nivel de independencia de estos factores; es decir, buscaremos estimaciones generales ampliamente válidas.

Concepto Complejidad Algoritmos

Aritmética de notación

• Existen diversas formas para representar nuestros algoritmos y estas representaciones pueden ayudarnos en la comprensión de los mismos; así como poderlos trasladar a algún lenguaje de programación.

• Notaciones matemáticas– Función factorial: Es el producto de los n

números enteros positivos que van desde 1 hasta n

Ejemplo:n! 2!= 1.2=2 3!= 1.2.3=6 4!=1.2.3.4=24

NOTACIONES:

NOTACIONES:

• Notaciones matemáticas– Simbolo de la suma (sumatorio)El simbolo sumatorio es ∑

Ejemplo:Sea la secuencia a1, a2, a3, a4,……..an

Las sumasa1+a2+a3+a4+ ……. +an = ∑ a n

J=1

NOTACION INFIJA:Los operadores aparecen en medio de los operandos. A + B, A – 1, E/F, A * C , A ^ B , A + B + C

NOTACION PREFIJA:El operador aparece antes de los operandos. + AB, - A1, /EF, *AC, ^AB, ++ABC

NOTACION POSTFIJA:El operador aparece al final de los operandos. AB+, A1-, EF/, AC*, AB^, AB+C+

NOTACIONES:NOTACIONES:

Estructuras de control

• Lógica secuencial: se ejecuta en una secuencia obvia.

Algoritmo Diagrama de flujo

Modulo A

Modulo B

Modulo C

Modulo A

Modulo B

Modulo C

Estructuras de control

• Lógica Selectiva: Utiliza un conjunto de condiciones que implica la ejecución de alguna alternativa entre varias. Este tipo de estructuras reciben el nombre de estructura condicionadas

– Alternativa simple– Alternativa doble– Alternativa múltiple

Estructuras de control

• Alternativa simple: si condición, entonces: [Modulo A] [Final de la estructura condicional]

• Alternativa doble: si condición, entonces: [Modulo B] [Fin de la estructura condicional]

Estructuras de control

• Alternativa doble: si condicion(1), entonces: [Modulo A1] si No Si condicion(2), entonces: [Modulo A2] si No Si condicion(M), entonces: [Modulo AM] si No: [Modulo B] [Final de la estructura condicional]

Estructuras de control

• Lógica iterativa (flujo repetitivo): ciclos

– Ciclo Repetir-MientrasRepetir-Mientras condición:

[Modulo][Fin del ciclo]

Ejemplo de un Algoritmo con búsqueda secuencial.

1. [inicializar]. K:=1 y LUG:=02. Repetir paso 3 y 4 mientras LUG=0 y K<=N.3. Si ITEM=DATO[K], entonces: LUG:=K.4. K:= K+1. [Incrementamos el contador] [Fin del ciclo del paso 2].5.[¿lo hemos encontrado?] Si LUG=0, entonces:

Escribir: ITEM no pertenece al arreglo DATOS. Si No:

Escribir: LUG es la posición que ocupa ITEM. [Fin de la estructura condicional].6. Salir

La complejidad esta dada por?

el número de comparaciones C entre ITEM y DATOS[K]Caso peor: Que ITEM sea el Ultimo Elemento

Complejidad

• Analizar algoritmos es la tarea mas costosa en el diseño de los algoritmos.

Por que ? • Legibilidad• Costo en mantenimiento• Se tienen que aportar criterios que midan la

eficiencia

Factores que miden la eficiencia de un algoritmo

• Por el tiempo de ejecución (ordenación o búsqueda)

• Por el espacio (memoria)

Relación espacio-tiempoTenemos un archivo con datos de nombres seguro social etc.

Si se desea encontrar un nombre cual es el mejor método?

la busqueda binaria

Si lo que conocemos es el numero de seguro que método es mejor?

La busqueda secuencial , Pero implica mayor tiempo

Como solucionarlo:

Como seleccionamos un algoritmo?

Algoritmos

¿Qué es un algoritmo?

es un conjunto finito de instrucciones o pasos que sirven para ejecutar una tarea o resolver un problema dado.

Características de los algoritmos:

1. Precisión: los pasos se enuncian con precisión.

2. Entrada: el algoritmo recibe una entrada de datos

3. Salida: el algoritmo produce una salida de información

Algoritmos

Análisis de algoritmosIntroducción

Es difícil determinar la cantidad exacta de ejecución de un algoritmo ya que esto depende de:

• Como se codifico el programa

• Que computadora se utilizara

• Que datos debe utilizar el programa

Análisis de algoritmosIntroducción: Tasa de crecimiento

A medida que crece un elemento del programa, generalmente crece el tiempo de ejecución del mismo.

Esto es que el tiempo de ejecución varia según el tamaño de la entrada.

Observando estas variaciones se puede determinar la tasa de crecimiento del programa.

Tasa de crecimiento: Es una medida importante de la eficiencia de un programa ya que predice cuanto tiempo se requerirá para entradas muy grandes de un determinado problema.

Análisis de algoritmos

Para determinar la eficiencia de un programa debemos de considerar:

• El tiempo• El espacio

La complejidad del espacio de un programa.- Es la cantidad de memoria que se necesita para ejecutar hasta la compleción

(terminación)

La complejidad del tiempo de un programa.- Es la cantidad de tiempo de computadora que se necesita para Ejecutar hasta la compleción (terminación)

Introducción: Consideraciones de eficiencia

¿Cómo decidir cuál de los algoritmos es mejor (tiempo de ejecución y espacio de memoria)?

En ocasiones pueden existir varios algoritmos para resolver una aplicación particular (A1, A2, …,An).

Solución 1 (a posteriori, medida experimental). La solución más sencilla parece ser implementar los algoritmos en algún lenguaje de programación y medir el tiempo de ejecución que cada uno de ellos requiere para resolver el problema.

Solución 2 (a priori, medida teórica). Estableciendo una medida de calidad de los algoritmos, que nos permita compararlos sin necesidad de implementarlos.

Análisis de algoritmosIntroducción

En la solución 1, resulta muy costoso (por no decir imposible), implementar todos los algoritmos para poder realizar la comparación de los tiempos de ejecución.

Factores que influyen en el tiempo de ejecución:

•La velocidad de operación de la computadora en que se ejecuta. Es diferente ejecutar el programa en un micro 80386, que en un pentium de 1.83 Ghz.

•El compilador utilizado (calidad del código generado). Cada compilador utiliza diferentes estrategias de optimización, siendo algunas más efectivas que otras.

•La estructura del algoritmo para resolver el problema.

Análisis de algoritmosIntroducción

En la solución 2, lo ideal, al hacer la evaluación de la eficiencia del algoritmo, sería encontrar una función matemática que describiera de manera exacta el tiempo que dura el algoritmo al ejecutarse, con una entrada de n datos - TA(n) –

En muchos casos, el cálculo de la función matemática no se puede realizar, ya que depende de la calidad o contenido de la entrada, se ilustra a continuación:

for (int i=0; i < N && V[i]!=busca; i++);

existe=i<N

V busca Operaciones Tiempo Mseg

5 6 7 8 9 10 5 i=0

0<6 && v[0]=! 5

existe= 0<6

1

1

1

TA(n)= 3

Análisis de algoritmosIntroducción

V busca Operaciones Tiempo Mseg

5 6 7 8 9 10 9 i=0

0<6 && vec[0]=! 9 ; i++

1<6 && vec[1]=! 9 ; i++

2<6 && vec[2]=! 9 ; i++

3<6 && vec[3]=! 9 ; i++

4<6 && vec[4]=! 9

existe= 4<6

1

2

2

2

2

1

1

TA(n)= 11

Análisis de algoritmos

Esto implica que, por más que se conozca el tamaño de los datos de entrada, es imposible (para muchos problemas) determinar el tiempo de ejecución para cada una de las posibles entradas.

Introducción

Análisis de Algoritmos

Usualmente el análisis de un algoritmo incluye:

• Un caso medio

• Un caso pesimista

• Un caso optimista

que tan cerca al caso promedio trabaja el algoritmo, Notación Θ (theta)peor caso

mejor caso

Notación O (big-oh)

Notación Ω (big-omega)

Nosotros trabajaremos con el TA(n) en el peor de los casos (O), ya que es mucho más fácil definir cuál es el peor de los casos, que considerarlos todos o incluso que considerar el caso promedio.

TA(n)=tiempo que se demora el algoritmo A, en el peor de los casos, para encontrar una solución a un problema de tamaño n.

Introducción

Análisis de Algoritmos

Concepto de complejidad:

Es tratar de encontrar un función f(n), que acote el crecimiento de la función tiempo, para poder decir:

Que en ningún caso TA(n) se comporta peor que f al aumentar el tamaño del problema.

Así sea T(n) el tiempo de ejecución de algún programa, medido por una función de la entrada de tamaño n, esta función supondrá que:

1. El argumento n es un entero no negativo2. T(n) es no negativo para todos los argumentos n

Complejidad

TA (n) es un O(f(n)), leído como “O de f(n)”, si existe una constante positiva c, tales que, TA(n) <= cf(n)

Cuando se dice que T(n)=O(f(n)) se esta garantizando que la funcion T(n) crece a una velocidad no mayor que f(n)

Así f(n) es una cota superior de T(n)

Y

T(n) es una cota inferior de f(n)

n

Análisis de Algoritmos

Al afirmar que un algoritmo es O (f(n)), se está diciendo que al aumentar el número de datos que debe procesar, el tiempo del algoritmo va a crecer a como crece f en relación a n

Complejidad

TA(n) más comunes

O(1) constante

O(log n) logarítmico

O(n) lineal

O(n log n) Casi-lineal

O(n2) cuadrático

O(na) Polinomial a>2

O(an) Exponencial, a>2

O(n!) factorial Crecimiento de las funciones típicas de complejidad de algoritmos

Complejidad

Análisis de Algoritmos

O(1) Significa que la mayoría de las instrucciones se ejecutan una vez o muy pocas

O(log n) El programa es más lento cuanto más crezca N,

O(n2) Suele ser habitual cuando se tratan pares de elementos de datos, como por ejemplo un bucle anidado doble. Si N se duplica, el tiempo de ejecución aumenta cuatro veces.

• O(n)O(n) es mas eficiente que el es mas eficiente que el O(n2)O(n2)

• O(log n)O(log n) es mas rápido que es mas rápido que O(n log n)O(n log n) y y

a su vez es mas rápido que a su vez es mas rápido que O(n2)O(n2)

Análisis de Algoritmos

• Logaritmo de un numero: Es el exponente a que hay que elevar otro número llamado base para obtener el numero dado

• Base: cualquier numero positivo

5º=15¹=55²=255³=125

Siendo la base el 5 el logaritmo de

Log 1 es 0 , y cero es el exponente al que hay que elevar la base 5Log 5 es 1Log 25 es 2

Logaritmo

Los algoritmos de tipo polinómico (O(nª)) no son una maravilla, y se enfrentan con dificultad a problemas de tamaño creciente.

Mientras complejidades del orden O(n2) y O(n3) suelen ser efectivamente abordables, prácticamente nadie acepta algoritmos de orden O(n100), por muy polinómicos que sean.

Complejidad

Análisis de Algoritmos

Aritmética en notación O

Análisis de Algoritmos

Para facilitar el cálculo de la complejidad de un algoritmo es necesario desarrollar aritmética en notación O, de tal manera que sea posible dividir el algoritmo y, a partir del estudio de sus partes, establecer el cálculo global.

Teorema 1:

Si TA(n) es O( k f(n) ) TA(n) es O( f(n) )

Este teorema expresa una de las bases del análisis de algoritmos: lo importante no es el valor exacto de la función que ocota el tiempo, sino su forma. Esto permite eliminar todos los Factores constantes de la función cota.

Ejemplo: un algoritmo que es O(2n) también es O(n)

un algoritmo que es O(6n2+2) también es O(n2)

un algoritmo que es O(5+3n+2) también es O(n)

Aritmética en notación O

Análisis de Algoritmos

Teorema 2:

Si A1 y A2 son segmentos de un algoritmo, tales que TA1(n) es O(f1(n)) y TA2(n) es O(f2(n)), el tiempo empleado para ejecutarse A1 seguido de A2 es O(max(f1(n), f2(n))).

Esto quiere decir que la complejidad del programa resultante es igual a la complejidad del bloque más costoso.

Ejemplo:

a=1;

b=1;

c=1;

O(1)

Una asignación que no tiene llamadas a funciones se ejecuta en un tiempo constante, sin depender del número de datos del problema.

TA(n) es O(max(1,1,1))

Aritmética en notación O

Análisis de Algoritmos

Teorema 3

Sea A un algoritmo que se forma:

A2

A1for( i=0 ; i<n ; i++)

for( j=0 ; j<n ; j++)

cont++;

A

Tal que TA2 es O(f2(n)) y TA1 es O(f1(n)), el tiempo de ejecución del programa

Completo TA(n)=TA1(n) * TA2(n) es O(f1(n) * O(f2(n))

Aritmética en notación O

Análisis de Algoritmos

for(i=0; i<5 ; i++)

a[i]=0;Complejidad del programa O(1)

a[0]=0;a[1]=0;

a[2]=0;a[3]=0;

A[4]=0;

Donde: en los bucles con contador explícito, podemos distinguir dos casos, que el tamaño N forme parte de los límites o que no. Si el bucle se realiza un número fijo de veces, independiente de N, entonces la repetición sólo introduce una constante multiplicativa que puede absorberse.

for (int i= 0; i < K; i++) { algo_de_O(1) } K*O(1) = O(1)

K= constante

El tiempo de ejecución va a depender, del tamaño del N.

Aritmética en notación O

Análisis de Algoritmos

Si el tamaño N aparece como límite de iteraciones ...

for (int i= 0; i < N; i++) { algo_de_O(1) } N * O(1) = O(n)

for (int i= 0; i < N; i++) {

for (int j= 0; j < N; j++) {

algo_de_O(1)

}

}

N * N * O(1) = O(n2)

Ciclos anidados

for (int i= 0; i < N; i++) {

for (int j= 0; j < M; j++) {

algo_de_O(1)

}

}

N * M * O(1) = O(n*m)

for (int i= 0; i < N; i++) {

for (int j= 0; j < i; j++) {

algo_de_O(1)

}

}

el bucle exterior se realiza N veces, mientras que el interior se realiza 1, 2, 3, ... N veces respectivamente. En total, 1 + 2 + 3 + ... + N = N*(N+1)/2 -> O(n2)

El caso peor es cuando j se

ejecuta N veces

Aritmética en notación O

Análisis de Algoritmos

Bucles con la variable de control no lineal (while)

c= 1;

while (c < N) {

algo_de_O(1)

c= 2*c;

} El valor inicial de c es 1. Al final del ciclo c tiene el valor de 2k donde k es el número de iteraciones

El número de iteraciones es tal que 2k <= N => k Log2 (N)

Y por tanto la complejidad del bucle es O(log n)

El problema se reduce a encontrar una función que acote el número de iteraciones del ciclo, ya que nunca va entrar n veces al ciclo.

Pero dado que en cada iteración se reduce 2*c, es mejor como cota del número de iteraciones una función 2k.

Aritmética en notación O

Análisis de AlgoritmosA 4 iteraciones

Iteraccion1 c = 2*1 = 2

Iteraccion2 c = 2*2 = 4

Iteraccion3 c = 2*4 = 8

Iteraccion4 c = 2*8 = 16

BASE =2

LOG 4 = 16

Aritmética en notación O

Análisis de Algoritmos

if

El tiempo de ejecución del if se puede acotar con el tiempo de evaluación de la condición y el tiempo de ejecución más demorado (de la parte cierta o parte falsa) de la estructura condicional.

If (n<0)

return 0;

else

return 1;

La condición n<0 es de O(1), porque toma un tiempo constante ejecutarla, de igual forma sucede con los return ( O(1) ).

O(max(1,1))=O(1)

int Buscar(int [] a, int c){ int j; j=0; WHILE (j < n && a[j]< c) { j=j+1; } if ( j < n ) return j; else return -1; }

Tiempo de ejecución

Calcular la complejidad:

Análisis de Algoritmos

O(1)n*O(1)= O(n)

O(1)

O(1)O(1)

O(1)O(max(1,1,1))= O(1)

TA(n)=O(max(1,n,1)=O(n)

int Buscar(int [] a, int c){ int j; j=0; (* 1 *) WHILE (a[j]< c && j < n) (* 2 *) { j=j+1; (* 3 *) } if ( a[j]==c ) (* 5 *) return j; (* 6 *) else return -1; (* 7 *)}

Para determinar el tiempo de ejecución, calcularemos primero el número de operaciones elementales (OE) que se realizan:

– En la línea (1) se ejecuta 1 OE (una asignación).

– En la línea (2) se efectúa la condición del bucle, con un total de 4 OE (dos comparaciones, un acceso al vector, y un &&).

– La línea (3) está compuesta por un incremento y una asignación (2 OE).

– La línea (5) está formada por una condición y un acceso al vector (2 OE).

– La línea (6) contiene un RETURN (1 OE) si la condición se cumple.

– La línea (7) contiene un RETURN (1 OE), cuando la condición del IF anterior es falsa.

Tiempo de ejecución, calculando el numeró de operaciones

Análisis de Algoritmos

En el caso peor:

Tiempo de ejecución

Análisis de Algoritmos

• se efectúa la línea (1),

• el bucle se repite n veces hasta que se cumple la segunda condición,

• después se efectúa la condición de la línea (5) y el método acaba al ejecutarse la línea (7).

• Cada iteración del bucle está compuesta por las líneas (2) y (3), junto con una ejecución adicional de la línea (2) que es la que ocasiona la salida del bucle. Por tanto el tiempo de ejecución es:

adicional nT(n) = 1+ ((∑ (4 + 2) +4 ) +2 + 1 = 1+4n+2n+4+2+1 =6n+8=O(n) i=1

Tiempo de ejecución: calcular la complejidad directa y con operaciones OE

Análisis de Algoritmos

for( i=0; i<n ; i++)

for( j=0; j<n ; j++)

m3[i][j]=m1[i][j]+m2[i][j]; O(1)N*O(1)=O(n)

N*O(n)=O(n2)

En la línea 3 se ejecuta 4 OE

n nT(n) =1+ ∑(3 + 1+∑ (3+4 ))= i=1 J=1

En la línea 1 se ejecuta 4 OE, una inicialización, una comparación y un incremento

En la línea 2 se ejecuta 4 OE, una inicialización, una comparación y un incremento

n 1+ ∑(3 + 1+7n) = i=1

1+ 4n +7n2 =

O(n2)

Inicialización

Tiempo de ejecución

Análisis de Algoritmos

int PosMenor(int vec[ ], int desde, int N) {

int i,menor=desde;

for(i=desde+1 ; i<N; i++) {

if(vec[i]<vec[menor])

menor=i;

}

return menor;

}

O(1)

O(1)O(max(1,1))=O(1)

N*O(1)=O(n)

El ciclo i en el peor de los

casos recorre todos los

elementos

TA(n)=1+2+∑(3+3+1)+3+1 = 7n+7 = O(n)i=1

n

void ordenar(int vec[], int N)

{ int i, temp, pos;

for(i=0 ; i< N-1 ; i++)

{ pos=PosMenor(vec,i,N);

temp=vec[i];

vec[i]=vec[j];

vec[j]=temp;

}

}

Tiempo de ejecución

Análisis de Algoritmos

O(n)

O(1)

O(1)

O(1)

O(max(n,1,1,1)) = O(n) N*O(n)=O(n2)

i=1

nTA(n)=1+∑(4+ 1+(1+2+ ∑(3+3+1)+3+1) + 5)+4=

i=1

n TA(n)=1+ ∑(4+1+( 7n + 7)+5)+4=

i=1

n

= 7n2+17n+5

=O(n2)

Llamada posmenor

1+4n+n+7n2+7n+5n+4

Tiempo de ejecución

Análisis de Algoritmos

Calcular la complejidad del siguiente método ( n es un entero positivo).

void misterio (int N)

{ int k,i;

i=1;

while (k<=N)

{ K=i;

while (k <=N)

k++;

k=1;

while (k<=i)

k++;

i++

}

}

Tiempo de ejecución

Análisis de Algoritmos

Calcular la complejidad del siguiente método ( n es un entero positivo).

void misterio (int N)

{ int k,i;

i=1;

while (k<=N)

{ K=i;

while (k <=N)

k++;

k=1;

while (k<=i)

k++;

i++

}

}

O(1)

nO(1)

n

O(1)O(1)

n

O(1)

O(1)

n*O(1) = O(n)

n*O(1) = O(n)

O(max(1,n,,n,1))=O(n)

n*O(n) = O(n2)

O(max(1,n2))=O(n2)

Calcular la complejidad del siguiente método ( n es un entero positivo).

void misterio (int N)

{ int k,i,t;

i=1;

while (i<=N-1)

{ K=I+1;

while (k<=N)

{ t=1;

while (t<=k)

t++;

k++;

}

i++;

}

}

Tiempo de ejecución

Análisis de Algoritmos

Calcular la complejidad del siguiente método ( n es un entero positivo).

void misterio (int N)

{ int k,i,t;

i=1; O(1)

while (i<=N-1) N

{ K=I+1; O(1)

while (k<=N) n N*O(N)=O(N2)

{ t=1; o(1)

while (t<=k) n N*O(1)=O(N)

t++; o(1)

k++; o(1)

}

i++; O(1)

}

}

Tiempo de ejecución

Análisis de Algoritmos

O(N3)

Complejidad en espacio

Análisis de Algoritmos

El cálculo de la complejidad en espacio de un algoritmo es un proceso sencillo que se realiza mediante el estudio de las estructuras de datos y su relación con el tamaño del problema.

Decir que un programa es de O(n) en espacio significa que sus requerimientos de memoria aumentan proporcionalmente con el tamaño del problema.

Ejemplo: int v []=new int[N];

Para un programa con complejidad O(n2) en espacio, la cantidad de memoria que se necesita para almacenar lo datos crece con el cuadrado del tamaño del problema.

Ejemplo: int v []=new int[N*N];

Selección de un algoritmo

Análisis de Algoritmos

Factores que se deben tener en cuenta para la selección de un algoritmo:

• La complejidad en tiempo del algoritmoEs una primera medida de calidad, y establece su comportamiento cuando el número de datos a procesar es muy grande.

• La complejidad en espacio del algoritmoEs una medida de la cantidad de espacio que necesita el algoritmo para representar la información. Sólo cuando esa complejidad resulta razonable es posible utilizar este algoritmo con seguridad. Si las necesidades de memoria crecen desmesuradamente con respecto al tamaño del problema, el rango de utilidad del algoritmo es bajo y se debe descartar.

Selección de un algoritmo

Análisis de Algoritmos

• El valor de la constante asociada con la función de complejidad

Si hay dos algoritmos A1 y A2 de complejidad O(f(n)), el estudio de la función cota debe de hacerse de una manera más profunda y precisa en ambos casos, para tratar de establecer la que tanga menos constantes.

Selección De Un Algoritmo

Una de las características primordiales en la selección de un algoritmo es que este sea sencillo de entender calcular codificar y depurar, así mismo que utilice eficientemente los recursos del ordenador y se ejecute con la mayor rapidez posible con un eficaz uso de memoria dinámica y estática. También para seleccionar correctamente el mejor algoritmo es necesario realizar estas preguntas: ¿Qué grado de orden tendrá la información que vas a manejar? Si la información va a estar casi ordenada y no quieres complicarte, un algoritmo sencillo como el ordenamiento burbuja será suficiente. Si por el contrario los datos van a estar muy desordenados, un algoritmo poderoso como Quicksort puede ser el más indicado. Y si no puedes hacer una presunción sobre el grado de orden de la información, lo mejor será elegir un algoritmo que se comporte de manera similar en cualquiera de estos dos casos extremos.

¿Qué cantidad de datos vas a manipular? Si la cantidad es pequeña, no es necesario utilizar un algoritmo complejo, y es preferible uno de fácil implementación. Una cantidad muy grande puede hacer prohibitivo utilizar un algoritmo que requiera de mucha memoria adicional.

¿Qué tipo de datos quieres ordenar? Algunos algoritmos sólo funcionan con un tipo específico de datos (enteros, enteros positivos, etc.) y otros son generales, es decir, aplicables a cualquier tipo de dato. ¿Qué tamaño tienen los registros de tu lista? Algunos algoritmos realizan múltiples intercambios (burbuja, inserción). Si los registros son de gran tamaño estos intercambios son más lentos.’‘’