Está en la página 1de 33

Universidad Nacional Micaela Bastida de Apurmac

Departamento de Ingeniera

Escuela Acadmico Profesional de


Ingeniera Informtica y Sistemas

MANUAL PARA EL ANLISIS DE LA


COMPLEJIDAD DE LOS ALGORITMOS

Curso: Algortmica III

Docente: Ing. Erech, Ordoez Ramos

Abancay - 2013.
Contenido

Introduccin ....................................................................................................................................... 3

Objetivo del manual ........................................................................................................................... 4

Eficiencia y complejidad .................................................................................................................... 4

Criterios para medir la eficiencia y complejidad de un algoritmo ................................................. 4

Eficiencia temporal ........................................................................................................................ 4

Operaciones Elementales (OE) ...................................................................................................... 6

Reglas generales para el clculo del nmero de OE ...................................................................... 7

Anlisis de mejor, peor y caso medio del algoritmo ...................................................................... 9

Asntotas........................................................................................................................................... 16

Propiedades de los Conjuntos O(f(n)) .......................................................................................... 17

rdenes de complejidad ................................................................................................................... 20

Complejidad de algoritmos recursivos ............................................................................................. 21

Clasificacin de funciones recursivas .......................................................................................... 22

Ecuaciones de Recurrencia............................................................................................................... 23

Bibliografa ...................................................................................................................................... 33

Pg. 2
Complejidad de los algoritmos recursivos

Introduccin

Este Manual esta dirigido a todos los estudiantes de la Escuela Acadmico

Profesional de Ingeniera Informtica y Sistemas, quienes como parte de su formacin

profesional, hacen clculos de la complejidad de los algoritmos y as saber su eficiencia,

es decir el tiempo que tardar en ejecutarse y mejorar el mismo si es factible.

Por lo tanto el presente Manual nos ha de permitir medir de alguna forma el costo

(en funcin del tiempo) que consume un algoritmo para encontrar la solucin y nos

permitir la posibilidad de comparar distintos algoritmos que resuelven un mismo

problema.

Docente: Ing. Erech Ordoez Ramos Pg. 3


Complejidad de los algoritmos

Objetivo del manual

Proporcionar al estudiante una gua que permita afianzar sus conocimientos


relacionados al anlisis de la complejidad de los algoritmos.

Eficiencia y complejidad

Una vez dispongamos de un algoritmo que funciona correctamente, es necesario


definir criterios para medir su rendimiento o comportamiento. Estos criterios se centran
principalmente en su simplicidad y en el uso eficiente de los recursos.
De ah que muchas veces prime la simplicidad y legibilidad del cdigo frente a
alternativas ms crpticas y eficientes del algoritmo.

Criterios para medir la eficiencia y complejidad de un algoritmo

Simplicidad
Uso eficiente de los recursos:
o el espacio (memoria que utiliza)
o y el tiempo (lo que tarda en ejecutarse).

Eficiencia temporal

Depender de diversos factores como son:


los datos de entrada que le suministremos
La calidad del cdigo generado por el compilador para crear el programa objeto
La naturaleza y rapidez de las instrucciones mquina del procesador concreto que
ejecute el programa y
La complejidad intrnseca del algoritmo.

Existen dos estudios posibles sobre el tiempo:


1ro Medida terica (a priori): Consiste en obtener una funcin que acote (por arriba
o por abajo) el tiempo de ejecucin del algoritmo para unos valores de entrada
dados.
(Se vera en las clases tericas)
2da Medida real (a posteriori): Consistente en medir el tiempo de ejecucin del
algoritmo para unos valores de entrada dados y en un ordenador concreto.

Docente: Ing. Erech Ordoez Ramos Pg. 4


Complejidad de los algoritmos

(Se vera en la prcticas de laboratorio). Consiste en ejecutar casos de prueba, haciendo


medidas para:
una mquina concreta,
un lenguaje concreto,
un compilador concreto y
datos concretos.

La unidad de tiempo a la que debe hacer referencia estas medidas de eficiencia se


denotan por T(n) en donde n es el tamao de entrada.
T(n): Indica el nmero de instrucciones ejecutadas por un ordenador idealizado.

Por lo tanto un algoritmo tarda un tiempo de T(n).

Principio de Invarianza
Dado un algoritmo y dos implementaciones suyas I1 e I2, que tardan T1(n) y T2(n)
segundos respectivamente, el Principio de Invarianza afirma que existe una constante real
c > 0 y un nmero natural n0 tales que para todo n n0 se verifica que T1(n) cT2(n).

Es decir, el tiempo de ejecucin de dos implementaciones distintas de un algoritmo dado


no va a diferir ms que en una constante multiplicativa.

Con esto podemos definir sin problemas que un algoritmo tarda un tiempo del orden
de T(n) si existen una constante real c > 0 y una implementacin I del algoritmo que tarda
menos que cT(n), para todo n tamao de la entrada.

Dos factores a tener muy en cuenta son la constante multiplicativa y el n0 para los que
se verifican las condiciones, pues si bien a priori un algoritmo de orden cuadrtico es
mejor que uno de orden cbico, en el caso de tener dos algoritmos cuyos tiempos de
ejecucin son 106n2 y 5n3 el primero slo ser mejor que el segundo para tamaos de la
entrada superiores a 200.000.

El comportamiento de los algoritmos cambia notablemente para diferentes entradas,


por lo cual se estudia tres casos para un mismo algoritmo:

Docente: Ing. Erech Ordoez Ramos Pg. 5


Complejidad de los algoritmos

Caso peor: Corresponde a la traza (secuencia de sentencias) del algoritmo que


realiza ms instrucciones.
Caso mejor: Corresponde a la traza (secuencia de sentencias) del algoritmo que
realiza menos instrucciones.
Caso medio: Corresponde a la traza (secuencia de sentencias) del algoritmo que
realiza un promedio de instrucciones.

De los tres casos el que consideramos de mayor importancia es el caso peor, por las
siguientes razones:
Es el ms informativo (el caso mejor suele ser trivial).
Nos permitir acotar superiormente el consumo de recursos: sabremos que nuestro
programa
no consumir ms de lo estimado.
Es ms fcil de calcular que el caso medio.

Ejemplo
Sea A una lista de n elementos A1, A2, A3, ... , An. Ordenar significa permutar estos
elementos de tal forma que los mismos queden de acuerdo con un orden preestablecido.
Ascendente A1 <=A2 <=A3 ..........<=An
Descendente A1 >=A2 >=........>=An
Caso peor: Que el vector est ordenado en sentido inverso.
Caso mejor: Que el vector est ordenado.
Caso medio: Cuando el vector est desordenado aleatoriamente

Operaciones Elementales (OE)

Son las operaciones bsicas, asignaciones a variables, los saltos, llamadas a funciones y
procedimientos, retorno de ellos, etc.
Las comparaciones lgicas y el acceso a estructuras indexadas, como los vectores y
matrices. Cada una de ellos cuenta como 1 OE.

Por lo tanto al medir el tiempo, siempre lo haremos en funcin del nmero de OEs,
para un tamao de entrada dado.

Docente: Ing. Erech Ordoez Ramos Pg. 6


Complejidad de los algoritmos

Reglas generales para el clculo del nmero de OE

La siguiente lista presenta un conjunto de reglas generales para el clculo del nmero de
OE, siempre considerando el peor caso.

El tiempo de ejecucin de una secuencia consecutiva de instrucciones se calcula


sumando los tiempos de ejecucin de cada una de las instrucciones.
El tiempo de ejecucin de la sentencia CASE C OF v1:S1|v2:S2|...|vn:Sn END;
es T = T(C) + max{T(S1),T(S2),...,T(Sn)}. Obsrvese que T(C) incluye el tiempo
de comparacin con v1, v2 ,..., vn.
El tiempo de ejecucin de la sentencia IF C THEN S1 ELSE S2 END; es T =
T(C) + max{T(S1),T(S2)}.
El tiempo de ejecucin de un bucle de sentencias WHILE C DO S END; es T =
T(C) + (n iteraciones)*(T(S) + T(C)). Obsrvese que tanto T(C) como T(S)
pueden variar en cada iteracin, y por tanto habr que tenerlo en cuenta para su
clculo.
Para calcular el tiempo de ejecucin del resto de sentencias iterativas (FOR,
REPEAT, LOOP) basta expresarlas como un bucle WHILE. A modo de ejemplo,
el tiempo de ejecucin del bucle:
FOR i:=1 TO n DO
S
END;
Puede ser calculado a partir del bucle equivalente:
i:=1;
WHILE i<=n DO
S; INC(i)
END;
El tiempo de ejecucin de una llamada a un procedimiento o funcin F(P1, P2,...,
Pn) es 1 (por la llamada), ms el tiempo de evaluacin de los parmetros P1,
P2,..., Pn, ms el tiempo que tarde en ejecutarse F, esto es, T = 1 + T(P1) + T(P2)
+ ... + T(Pn) + T(F). No contabilizamos la copia de los argumentos a la pila de
ejecucin, salvo que se trate de estructuras complejas (registros o vectores) que se
pasan por valor. En este caso contabilizaremos tantas OE como valores simples
contenga la estructura. El paso de parmetros por referencia, por tratarse
simplemente de punteros, no contabiliza tampoco.

Docente: Ing. Erech Ordoez Ramos Pg. 7


Complejidad de los algoritmos

El tiempo de ejecucin de las llamadas a procedimientos recursivos va a dar lugar


a ecuaciones en recurrencia, que veremos posteriormente.
Ejemplo: Supongamos que tenemos la implementacin de un algoritmo de bsqueda
implementado en java y deseamos saber la complejidad bajo la medida terica (a priori)
del mtodo buscar.

public class Buscar


{
public static void main(String[] args)
{
Buscar B=new Buscar();
int posicion;
int array[]={0,2,4,6,10,81,104};
posicion=B.buscar(array,81); //Busca el elemento 81
System.out.println("La posicin es: " + posicion);
}
public int buscar(int a[],int c)
{
int j = 1; (* 1 *)
int n = a.length; (* 2 *)
while (a[j]<c && j<n) (* 3 *)
{
j=j+1; (* 4 *)
}
if (a[j]==c) (* 5 *)
return j; (* 6 *)
else
return 0; (* 7 *)
}
}
Analizamos el nmero de operaciones elementales (OE) que se realizan en cada lnea:
En la lnea (1) se ejecuta: 1 OE (una asignacin)
En la lnea (2) se ejecuta: 2 OE (una asignacin y una llamada a
funcin)
En la lnea (3) se ejecuta: 4 OE (dos comparaciones, un acceso al
vector y un AND)
En la lnea (4) se ejecuta: 2 OE (un incremento y una asignacin)
En la lnea (5) se ejecuta: 2 OE (una condicin y un acceso al vector)
En la lnea (6) se ejecuta: 1 OE (un retorno)
En la lnea (7) se ejecuta: 1 OE (un retorno)

Docente: Ing. Erech Ordoez Ramos Pg. 8


Complejidad de los algoritmos

Anlisis de mejor, peor y caso medio del algoritmo

1ro Mejor caso: Se ejecutan el menor nmero de lneas posibles


En la lnea (1) se ejecuta: 1 OE (una asignacin)
En la lnea (2) se ejecuta: 2 OE (una asignacin y una llamada a
funcin)
En la lnea (3) se ejecuta: 2 OE (porque se ejecuta la mitad de la
condicin)
En la lnea (5) se ejecuta: 2 OE (una condicin y un acceso al vector)
En la lnea (6) se ejecuta: 1 OE (un retorno)

Por lo tanto: T(n) = 1+2+2+2+1 = 8 OE

2do Peor caso: Se ejecutan el mximo posible de lneas de cdigo.


En la lnea (1) se ejecuta: 1 OE (una asignacin)
En la lnea (2) se ejecuta: 2 OE (una asignacin y una llamada a funcin)
En la lnea (3) se ejecuta: 4(n-1)+4 OE (Se ejecutan 4 operaciones en cada
vuelta del bucle)
En la lnea (4) se ejecuta: 2(n-1) OE (Se ejecutan 2 operaciones en cada
pasada del bucle mas 2 OE en la salida del bucle)
En la lnea (5) se ejecuta: 2 (una condicin y un acceso al vector)
En la lnea (6) se ejecuta: 1 OE (un retorno)

Por lo tanto: T(n) = 1+2+((4(n-1) +2(n-1)) +4)+2+1 = 6n+4 OE

O podemos expresar el mismo anlisis en trminos de sumatorias


n 1
T(n) 1 2 ( 4 2 ) 4 2 1 6n 4 OE
i 1

3ro Caso medio: En el caso medio, el bucle se ejecutar un nmero de veces entre 0 y
n1, y vamos a suponer que cada una de ellas tiene la misma probabilidad de suceder.
Como existen n posibilidades (puede que el nmero buscado no est) suponemos a priori
que son equiprobables y por tanto cada una tendr una probabilidad asociada de 1/n. Con
esto, el nmero medio de veces que se efectuar el bucle es de:

Docente: Ing. Erech Ordoez Ramos Pg. 9


Complejidad de los algoritmos

n 1
1 n 1
i n
i 0 2
Tenemos pues que n 1 2

T(n) 1 2 ( 4 2 ) 4 2 1 3n 7 OE
i 1

En la prctica no se trabaja con T(n) sino con funciones que clasifiquen estas
funciones acotando su valor asintticamente. Por ejemplo: si el T(n) de un algoritmo es:
10n 2
T(n) 2n
3
Diremos que T(n) pertenece O(n2) como lo veremos posteriormente en el tema de
asntotas.

Ejercicios:

1. Sea el algoritmo: calcular su complejidad en el mejor, peor y caso medio.

1. Read(n)
2. s=0
3. i=1
4. While(i<=1) do
5. s=s+1
6. i=i+1
7. End(While)
8. Write(n,s)

a. Mejor Caso: En el mejor de los casos no entra en el bucle While por lo cual se
ejecutan las siguientes operaciones elementales.

1. Read(n) 1 OE (acceso a una funcin)


2. s=0 1 OE (asignacin)
3. i=1 1 OE
4. While(i<=1) do 1 OE (evaluacin de la condicin)
5. s=s+1
6. i=i+1
7. End(While)
8. Write(n,s) 1 OE (acceso a una funcin)

t(n) = 5 OE

Docente: Ing. Erech Ordoez Ramos Pg. 10


Complejidad de los algoritmos

b. Peor Caso: En el peor caso se ejecuta todo el cdigo posible.

1. read(n) 1 OE
2. s=0 1 OE
3. i=1 1 OE
4. while(i<=1) do 1n +1 OE (n vueltas + 1 evaluacin de salida)
5. s=s+1 2n OE
6. i=i+1 2n OE
7. end(while)
8. write(n,s) 1 OE

t(n) = 5n+5 OE

c. Caso medio: En el caso medio como se explico en el ejercicio 1, los bucles se dividen
entre la mitad de vueltas que den los bucles, por lo cual se tiene:

1. Read(n) 1 OE
2. s=0 1 OE
3. i=1 1 OE
4. While(i<=1) do 1n/2+1 OE
5. s=s+1 2n/2 OE
6. i=i+1 2n/2 OE
7. End(While)
8. Write(n,s) 1 OE

t(n) = 5n/2+5 OE

2. Sea el algoritmo: calcular su complejidad en el mejor, peor y caso medio.

1. Read(n)
2. s=0
3. i=1
4. While(i<=1) do
5. s=s+1
6. i=i+1
7. End(While)
8. Write(n,s)

Docente: Ing. Erech Ordoez Ramos Pg. 11


Complejidad de los algoritmos

a. Mejor Caso: En el mejor de los casos no entra en el bucle While por lo cual se
ejecutan las siguientes operaciones elementales.

1. Read(n) 1 OE (acceso a una funcin)


2. s=0 1 OE (asignacin)
3. i=1 1 OE
4. While(i<=1) do 1 OE (evaluacin de la condicin)
5. s=s+1
6. i=i+1
7. End(While)
8. Write(n,s) 1 OE (acceso a una funcin)

t(n) = 5 OE

b. Peor Caso: En el peor caso se ejecuta todo el cdigo posible.

1. read(n) 1 OE
2. s=0 1 OE
3. i=1 1 OE
4. while(i<=1) do 1n +1 OE (n vueltas + 1 evaluacin de salida)
5. s=s+1 2n OE
6. i=i+1 2n OE
7. end(while)
8. write(n,s) 1 OE

t(n) = 5n+5 OE

c. Caso medio: En el caso medio como se explico en el ejercicio 1, los bucles se dividen
entre la mitad de vueltas que den los bucles, por lo cual se tiene:

1. Read(n) 1 OE
2. s=0 1 OE
3. i=1 1 OE
4. While(i<=1) do 1n/2+1 OE
5. s=s+1 2n/2 OE
6. i=i+1 2n/2 OE
7. end(while)
8. Write(n,s) 1 OE

t(n) = 5n/2+5 OE

Docente: Ing. Erech Ordoez Ramos Pg. 12


Complejidad de los algoritmos

En adelante consideraremos solo el caso peor por ser de mayor representatividad para
nuestros fines.

3. Sea el algoritmo: calcular su complejidad en el peor caso.

1. Read(n) La segunda vez que se ejecuta el ciclo


2. S=0
n=16/2=8
3. While n>1 do
4. S=S+1
5. n=n/2 La tercera vez que se ejecuta el ciclo
6. End(while)
n=8/2=4
7. Write (n,S)

En el algoritmo anterior, la variable La cuarta vez n=4/2=2


controladora del bucle es n, y dentro del
La quinta vez n=2/2=1
ciclo, n se divide por dos (2). Si hacemos
un seguimiento detallado y damos un
Y termina el ciclo, es decir, las
valor arbitrario a n=32, tendremos:
instrucciones del bucle se ejecutaron 5
veces.
La primera vez que se ejecuta el ciclo, la
variable n sale valiendo n=32/2=16.

Si en un inicio n=32 y el bucle termina dando 5 entradas, entonces la relacin que existe
entre 32 y 5 es: Log 2 32=5, por consiguiente cada instruccin del ciclo se ejecuta un
nmero de veces igual al logaritmo en base dos de n. Por lo tanto:

Docente: Ing. Erech Ordoez Ramos Pg. 13


Complejidad de los algoritmos

1. Read(n) 1 OE
2. S=0 1 OE
3. While n>1 do (Log2n)+1 OE
4. S=S+1 2*(Log2n) OE
5. n=n/2 2*(Log2n) OE
6. End(While)
7. Write (n,S) 1 OE

t(n) = 5 Log2n+3

4. Sea el algoritmo anterior modificado: calcular su complejidad en el peor caso.

1. Read(n)
2. S=0
3. While n>1 do
4. S=S+1
5. n=n/3
6. End(While)
7. Write (n,S)

Aqu la variable controladora se divide por 3 dentro del ciclo. Damos un valor
arbitrario a n para ver su comportamiento n=81, haciendo el seguimiento tenemos. En la
primera pasada n=27, en la segunda n=9, el la tercera n=3 y en la cuarta sale con n=1 y
finaliza el bucle. Ahora la relacin que existe entre n=81 y 4 vueltas del bucle es:
Log381=4.

Por lo tanto dependiendo por cuanto es dividido la variable controladora de un bucle,


obtendremos Log x n vueltas.

Ahora si analicemos nuestro algoritmo lnea por lnea, incluyendo las vueltas del
bucle, obtenemos:

1. Read(n) 1 OE
2. S=0 1 OE
3. While n>1 do (Log3n)+1
4. S=S+1 2*(Log3n)
5. n=n/3 2*(Log3n)
6. End(While)
7. Write (n,S) 1 OE

t(n) = 5 Log3n + 3

Docente: Ing. Erech Ordoez Ramos Pg. 14


Complejidad de los algoritmos

5. Sea el algoritmo de ordenamiento escrito en Delphi: Calcular su complejidad en el


peor caso.

1. Function ordenar(lista: array of Integer):integer;


2. var
3. n,i,j,aux:integer;
4. begin
5. n:=Length(lista);
6. for i:=0 to n-1 do
7. begin
8. for j:=i to n-1 do
9. begin
10. if lista[i]>lista[j] then
11. begin
12. aux:=lista[i];
13. lista[i]:=lista[j];
14. lista[j]:=aux;
15. end;
16. end;
17. end;
18. end;

Analicemos la complejidad lnea por lnea:

Nota: Para calcular el nmero de Operaciones Elementales del bucle FOR hacemos la
conversin a su equivalente bucle WHILE:

1. i=1 1OE
2. While i<=n do 1OE
1. for i:=1 to n do 3. Begin
2. begin 4. i:=i+1; 2OE
3. end; 5. End;

Como vemos una aproximada conversin en cuanto a su complejidad del bucle FOR al
WHILE es 4 OE por lo cual en adelante contabilizaremos a todo bucle FOR como 4 OE.

Docente: Ing. Erech Ordoez Ramos Pg. 15


Complejidad de los algoritmos

1. n:=Length(lista); 2 OE
2. for i:=0 to n-1 do (4+1)n +1OE multiplicado por n vueltas
3. begin
4. for j:=0 to n-1 do ((4+1)n+1) n OE se multiplican ambos bucles
5. begin
6. if lista[i]>lista[j] then 3n2 OE
7. begin
8. aux:=lista[i]; 2 n2 OE
9. lista[i]:=lista[j]; 3 n2 OE
10. lista[j]:=aux; 2 n2 OE
11. end;
12. end;
13. end;

t(n) = 15n2+6n+3

Asntotas

Como vimos anteriormente podemos calcular el tiempo terico t(n) de cualquier


algoritmo el cual nos ha de permitir comparar la potencia de dicho algoritmo
independientemente de la potencia de la mquina que los ejecute e incluso de la habilidad
del programador que los codifique. Por otra parte, de este anlisis nos interesa
especialmente cuando el algoritmo se aplica a problemas grandes. No debe olvidarse que
cualquier tcnica de ingeniera, que funciona, acaba aplicndose al problema ms grande
que sea posible: las tecnologas de xito, antes o despus, acaban llevndose al lmite de
sus posibilidades.

Las consideraciones anteriores nos llevan a estudiar el comportamiento de un


algoritmo cuando se fuerza el tamao del problema al que se aplica. Matemticamente
hablando, cuando n tiende al infinito. Es decir, su comportamiento asinttico.

Sean g(n) diferentes funciones que determinan el uso de recursos, pudiendo


existir infinidad de funciones g.

Lo que vamos a intentar es identificar familias de funciones, usando como


criterio de agrupacin su comportamiento asinttico.

Docente: Ing. Erech Ordoez Ramos Pg. 16


Complejidad de los algoritmos

Una familia de funciones que comparten un mismo comportamiento asinttico


ser llamada un Orden de Complejidad. Estas familias se designan con O( ).

Para cada uno de estos conjuntos se suele identificar un miembro f(n) que se
utiliza como representante de la familia, hablndose del conjunto de funciones g que
son del orden de "f(n)", denotndose como:

g IN O(f(n)) (g esta incluido en f(n))

Con frecuencia nos encontraremos con que no es necesario conocer el


comportamiento exacto, sino que basta conocer una cota superior, es decir, alguna
funcin que se comporte an peor.

La definicin matemtica de estos conjuntos debe ser muy cuidadosa para


involucrar ambos aspectos: identificacin de una familia y posible utilizacin como cota
superior de otras funciones menos malas:

Dcese que el conjunto O(f(n)) es el de las funciones de orden de f(n), que se


define como:

O(f(n)) = { g : INTEGER REAL+ / k y n0 / n > n0, g(n) k*f(n) }

O(f(n)) esta formado por aquellas funciones g(n) que crecen a un ritmo menor o igual que
el de f(n).

De las funciones g que forman este conjunto O(f(n)) se dice que estn
dominadas asintticamente por f, en el sentido de que para n suficientemente grande,
y salvo una constante multiplicativa k, f(n) es una cota superior de g(n).

Propiedades de los Conjuntos O(f(n))

Las primeras reglas slo expresan matemticamente el concepto de jerarqua de


rdenes de complejidad:

Docente: Ing. Erech Ordoez Ramos


Pg. 17
Complejidad de los algoritmos

a) La relacin de orden definida por

f(n) < g(n) f(n) IN O(g(n))


Es reflexiva: f(n) IN O(f(n))

y transitiva: f(n) IN O(g(n)) y g(n) IN O(h(n)) f(n) IN O(h(n))

b) f(n) IN O(g(n)) y g IN O(f(n)) O(f(n)) = O(g(n))

Las siguientes propiedades se pueden utilizar como reglas para el clculo de rdenes de
complejidad. Toda la maquinaria matemtica para el clculo de lmites se puede aplicar
directamente:

c) lim ()/() = f(n) IN O(g(n))


g(n) NOT_IN O(f(n))


O(f(n)) es subconjunto de O(g(n))

d) lim ()/() = f(n) IN O(g(n))


g(n) IN O(f(n))
O(f(n)) = O(g(n))

e) lim ()/() = f(n) NOT_IN O(g(n))


g(n) IN O(f(n))
O(f(n)) es superconjunto de O(g(n))

Ejemplo:

1. Demostrar que la funcin f (n) 0,01n no pertenece a O(n )


3 2

Para demostrar que f(n) no es de orden cuadrtico basta tener en cuenta que:

0,013
lim = lim 0.01 =
2

Docente: Ing. Erech Ordoez Ramos Pg. 18


Complejidad de los algoritmos

2. Sea = 2 + 5 y = 3 + 2 2


2 +5 2 +5 2+1 2 2
Entonces lim = () = 3 +22 = == = 6 = = 0
3 +22 3 2 +2

Por lo tanto ( ) y deducimos que:

( )

3. Sea = 2 + 5 y = 2


2 +5 2 +5 2+1 2
Entonces lim () = == = =2=1
2 2 2

Por lo tanto ( ) y deducimos que:

( )
=

4. Demostrar que la funcin f (n) 200n 300n pertenece a O(n )


2 2

Para demostrar que f(n) es de orden cuadrtico basta tener en cuenta que:

+
lim
= lim
+ =

Otra posibilidad es encontrar un nmero real c positivo y un natural no que


cumplan las condiciones de la definicin Basta tomar c=500 y no = 1 para que se
cumpla:
200n2+300n500n2 para cualquier n2, en efecto 200n2+300n500n2 implica que
ha de ser 300n300 n2 lo que a su vez implica que ha de ser 300300n, lo cual
ocurre para cualquier n mayor o igual que 1.

Docente: Ing. Erech Ordoez Ramos


Pg. 19
Complejidad de los algoritmos

rdenes de complejidad

Se dice que O(f(n)) define un "orden de complejidad". Escogeremos como


representante de este orden a la funcin f(n) ms sencilla del mismo. As tendremos:

O(1) orden constante

O(log n) orden logartmico

O(n) orden lineal

O(n log n)

O(n2) orden cuadrtico

O(na) orden polinomial (a > 2)

O(an) orden exponencial (a > 2)

O(n!) orden factorial

Docente: Ing. Erech Ordoez Ramos Pg. 20


Complejidad de los algoritmos

Complejidad de algoritmos recursivos

Recursividad: tcnica con la que un problema se resuelve sustituyndolo por otro


problema de la misma forma pero ms simple.

En general, un algoritmo recursivo tiene dos partes:

El caso base, que maneja una entrada simple que puede ser resuelta sin una
llamada recursiva
La parte recursiva, que contiene una o ms llamadas recursivas al algoritmo,
donde los parmetros estn en un sentido ms cercano al caso base, que la
llamada original.

Ejemplo: Definicin de factorial para n 0.

0! = 1
n! = n * (n-1)! si n>0

Es una herramienta muy potente, til y sencilla.

Ciertos problemas se adaptan de manera natural a soluciones recursivas; pero en


general, las soluciones recursivas son ms ineficientes en tiempo y espacio que las
versiones iterativas, debido a las llamadas a subprogramas, la creacin de variables
dinmicamente en la pila, la duplicacin de variables, etc.

En general, cualquier funcin recursiva se puede transformar en una funcin iterativa.

Ventaja de la funcin iterativa: ms eficiente en tiempo y espacio.


Desventaja de la funcin iterativa: en algunos casos, muy complicada; adems,
suelen necesitarse estructuras de datos auxiliares

Docente: Ing. Erech Ordoez Ramos


Pg. 21
Complejidad de los algoritmos

Si la eficiencia es un parmetro crtico, y la funcin se va a ejecutar frecuentemente,


conviene escribir una solucin iterativa.

La recursividad se puede simular con el uso de pilas para transformar un programa


recursivo en iterativo. Las pilas se usan para almacenar los valores de los parmetros del
subprograma, los valores de las variables locales, y los resultados de la funcin.

Clasificacin de funciones recursivas

a) Segn desde dnde se haga la llamada recursiva:


Recursividad directa: la funcin se llama a s misma.
Recursividad indirecta: la funcin A llama a la funcin B, y sta llama a A.

b) Segn el nmero de llamadas recursivas generadas en tiempo de ejecucin:


Funcin recursiva lineal o simple: se genera una nica llamada interna.
Funcin recursiva no lineal o mltiple: se generan dos o ms llamadas
internas.

c) Segn el punto donde se realice la llamada recursiva, las funciones recursivas


pueden ser:

Final: (Tail recursion): La llamada recursiva es la ltima instruccin que se


produce dentro de la funcin.
No final: (Nontail recursive function): Se hace alguna operacin al volver de
la llamada recursiva.

Las funciones recursivas finales suelen ser ms eficientes (en la constante


multiplicativa en cuanto al tiempo, y sobre todo en cuanto al espacio de memoria) que
las no finales. (Algunos compiladores pueden optimizar automticamente estas

Docente: Ing. Erech Ordoez Ramos Pg. 22


Complejidad de los algoritmos

funciones pasndolas a iterativas)

Ejemplo de funcin recursiva final: algoritmo de Euclides para calcular el mximo


comn divisor de dos nmeros enteros positivos.

mcd (a, b) = mcd (b, a) = mcd (a-b, b) si a > b


mcd (a, b-a) si a < b
a si a = b

Ecuaciones de Recurrencia

En un algoritmo recursivo, la funcin que establece su tiempo de ejecucin


viene dada por una ecuacin de recurrencia, donde en la expresin aparece la propia
funcin .
= , y en aparece la propia funcin .

Para resolver ese tipo de ecuaciones hay que encontrar una expresin no recursiva
de . (En algunos casos no es tarea fcil.)

A menudo, al plantear las ecuaciones que describen el costo de un algoritmo,


obtendremos ecuaciones de recurrencia, que describen el costo del algoritmo en funcin
de instancias ms pequeas del mismo. Como primer ejemplo veremos la solucin de las
torres de Hanoi.

El problema de las torres de Hanoi, tiene una solucin recursiva que se basa en
mover n 1 discos de A a B, luego el ms grande de A a C y finalmente los n 1 en B
haca C. Si definimos T (n) cantidad de movimientos de disco necesarios para resolver el
problema de las torres de Hanoi con n discos, obtenemos:

t(n) = 2 t(n 1) + 1

El +1 corresponde a mover el disco ms grande de A a C, cada t(n-1) corresponde a

Docente: Ing. Erech Ordoez Ramos


Pg. 23
Complejidad de los algoritmos

mover n 1 discos como si fuese el mismo problema de las torres de Hanoi (notar que
slo cambia a torre intermedia, la solucin es efectivamente la misma).

A continuacin veremos 5 mtodos de solucin para ecuaciones de recurrencia, las


torres de Hanoi servirn para el primero.

1. Primer mtodo: Suponer una solucin f(n), y usar la recurrencia para demostrar que
t(n) = f(n). La prueba se hace generalmente por induccin sobre n.

Veamos algunos valores para t(n) = 2 t(n 1) + 1. Primero debemos darnos un


caso base, cuntos movimientos se requieren para resolver el problema de las
torres de Hanoi con un solo disco: t(1) = 1.
n t(n)
1 1
2 3
3 7
4 15
Cuadro 1: Algunos valores de t(n)

De esta tabla no es tan directo ver la solucin, pero si escribimos la misma


tabla para t(n) + 1 obtenemos:

n t(n)+1
1 2
2 4
3 8
4 16
Cuadro 2: Algunos valores de t(n)+1

Aqu ya es posible notar que t(n)+1 = 2n o bien que t(n) = 2n 1. Esto en


principio es slo una especulacin y debemos ser capaces de probar que lo que
decimos es cierto. Esto se puede hacer por induccin sobre n.

Teorema (Torres de Hanoi) La solucin de la ecuacin

Docente: Ing. Erech Ordoez Ramos Pg. 24


Complejidad de los algoritmos

t(n) = 2 t(n1) + 1 es

t(n) = 2n 1.

Demostracin Por induccin sobre n:

Caso base: Para n = 1 tenemos que t(n) = 21 1 = 1, lo cual es correcto.

Paso inductivo: Asumamos que la hiptesis t(n) = 2n 1 es correcta para n y


probemos que se cumple para n + 1. Desarrollemos la ecuacin:

t(n + 1) = 2 t(n) + 1 (2)

t(n + 1) = 2(2n 1) + 1 (3)

t(n + 1) = 2n+1 2 + 1

t(n + 1) = 2n+1 1

Desde (2) a (3) se utiliza la hiptesis y desde ah se llega directamente al resultado


esperado.

Es importante tener en cuenta que cualquier solucin que encontremos con los
mtodos expuestos a continuacin pueden ser verificados utilizando esta misma
forma.

2. Segundo mtodo: Sustituir las recurrencias por su igualdad hasta llegar a cierta
( 0 ) que sea conocida.
Ejemplo:

int Fact (int n)


{
if (n <= 1)
return(1);
else
return( n * Fact(n-1));
}

Sea () el tiempo de ejecucin en el caso peor. Se escribe una ecuacin de

Docente: Ing. Erech Ordoez Ramos


Pg. 25
Complejidad de los algoritmos

recurrencia que acota a () superiormente como:

1 , 1
() =
(1) + 2 , > 1

1 : Tiempo de ejecucin del caso trivial 1 estructura if(n1) y la


funcin return(1);

> 1: tiempo requerido por Fact puede dividirse en dos partes:

(1) La llamada recursiva a FAct con 1.


2 El tiempo de evaluar la condicin ( > 1), la multiplicacin
de n Fact(n 1) y el acceso a return().

Entonces resolvemos la ecuacin de recurrencia:

Si () = (1) + 2 , entonces calculamos la parte recurrente:

() = (1) + 2 (I)

(1) = (2) + 2

(2) = (3) + 2

(3) = (4) + 2

Luego de ello sustituimos sus equivalentes en (I), hasta obtener el k-esimo termino
de las sustituciones.

() = (1) + 2
() = (2) + 2 + 2
() = (2) + 22
() = (3) + 2 + 22
() = (3) + 32

() = () + 2 (II)

Docente: Ing. Erech Ordoez Ramos Pg. 26


Complejidad de los algoritmos

Si sabemos que () = 1 , 1, entonces n = 1, (1) = 1


=1 =1

Reemplazando los valores conocidos en (II):


() = (1) + ( 1)2
() = ( 1)2 + 1

De donde podemos concluir que el tiempo de ejecucin del algoritmo es:


() = ( 1)2 + 1

3. Tercer mtodo: Resolucin de la Ecuacin Caracterstica

A) Primera forma

Este mtodo se aplica para ecuaciones de la forma:

() = ( 1 , 2 , , , )

Un ejemplo muy conocido son los nmeros de Fibonacci, cuya ecuacin es:

() = 1 + 2

Con los valores iniciales (0) =0 y (1) = 1.

Pare resolver ecuaciones de este tipo asumiremos () = y simplemente


reemplazamos:
() = 1 + 2
= 1 + 2 (6)
2 = + 1 (7)
2 1 = 0 (8)

Si resolvemos esa ecuacin obtenemos dos soluciones:

Docente: Ing. Erech Ordoez Ramos


Pg. 27
Complejidad de los algoritmos

1+ 5 1 5
1 = , 2 =
2 2

Cada valor por su cuenta es una solucin, como tambin los es la


combinacin lineal de ambos:
() = 1 1 + 2 2

Usando las condiciones inciales podemos obtener los valores de las


constantes 1 y 2 .
Usamos t(0) = 0 y t(1) = 1
t(0) = 0
= 1 + 2
0 = 1 + 2
1 = 2

Ahora, al reemplazar en la segunda condicin inicial, consideraremos 1 = 2 .


t(1) = 1
= 1 1 + 1 2
1 = 1 1 2
1 = 51
1
1 = 5

Obteniendo finalmente la solucin:


1 1+ 5 1 5
=
5 2 2

B) Segunda Forma

Para ecuaciones de la forma = 1 + con conocido para algn

Docente: Ing. Erech Ordoez Ramos Pg. 28


Complejidad de los algoritmos

0.
Teorema: La solucin para la ecuacin = 1 + es:

= +
=+1

Para alguna condicin inicial con 0.

Demostracin: La solucin puede ser deducida de la siguiente manera:

= 1 + 1 =
En esta ecuacin es una variable muda y puede escribirse como:
1 =

Si sumamos desde = + 1 hasta = obtenemos:

(() (1) ) =
=+1 =+1

La primera parte es una telescpica y sobreviven los trminos y ,


quedando:

=
=+1

Obteniendo finalmente:

=
=+1

Ejemplo (Ordenamiento por seleccin): En temas posteriores al curso veremos el


ordenamiento por seleccin, por el momento podemos adelantar que la ecuacin de
recurrencia que describe el del algoritmo es:

Docente: Ing. Erech Ordoez Ramos


Pg. 29
Complejidad de los algoritmos

= 1 + 1, 0 = 0

Usando la frmula tenemos:



=0+ 1
=1
( 1)
=
2

C) Tercera forma

Para ecuaciones de la forma = 1 + con alguna condicin inicial


con 0.

Teorema La ecuacin = 1 + , con constante y una condicin inicial


conocida con 0, tiene como solucin:


= +
=+1

Demostracin: Para demostrar la solucin obtenida basta tomar la ecuacin y


dividirla por :

1
= +

1 1
Notamos que = . Si definimos =
la ecuacion resultante es:
1

= 1 +

Usando el teorema propuesto obtenemos:


= 1 +

=+1

Docente: Ing. Erech Ordoez Ramos Pg. 30


Complejidad de los algoritmos




= +

=+1

= () +
=+1

Ejemplo (Torres de Hanoi) El problema de las torres de Hanoi, resuelto utilizando el


mtodo 1, se puede resolver usando este mtodo tambin. La ecuacin es:

= 2(1) + 1, 0 =0
La solucin es:


= 2 . 0 + 2
=1

=2 1

D) Cuarta Forma

Finalmente, para las ecuaciones de la forma = ( ) + obtendremos



una solucin exacta para = . Para simplificar el resultado, consideraremos
1 como condicin inicial conocida.

Teorema: La ecuacin = ( ) + , con 0 > 1 constantes tiene


como solucin:
()
()
= (1) +
= , 1
=1

Demostracin: Como estamos resolviendo la ecuacin de manera exacta para


potencias de , es decir, = , podemos reescribir la ecuacin en trminos de y
:

= + ( )

Si definimos = la ecuacin queda:

Docente: Ing. Erech Ordoez Ramos


Pg. 31
Complejidad de los algoritmos

= 1 +

Haciendo uso del Teorema propuesto para este caso obtenemos:




= 0 +
=1

Finalmente, = , = 0 = 1 , por lo que reemplazando


esos valores se obtiene:
log b ()

= log b () (1) + log b


( )
=1

Ejemplo (Merge-Sort): Otro algoritmo conocido de ordenamiento es MergeSort. La


ecuacin que describe el costo de este algoritmo es:
= 2 2 + , 1 =0

Por lo que la solucin es:


2 ()
2 ()
=2 1 + 2 2
2
=1
2 ()

= 2 2

=1

= 2 2
2
= 2 ()

Ejemplo (Bsqueda binaria): La ecuacin que representa el costo de la bsqueda


binaria es:
= 2 + 1, 1 =1

Si usamos el resultado del teorema anterior obtenemos:


2 ()

= 1 2 () 1 + 1 2
1
=1
2 ()

= 1 + 1
=1

= 1 + 2 ()

Docente: Ing. Erech Ordoez Ramos Pg. 32


Complejidad de los algoritmos

Bibliografa

Flres Rueda, Roberto. Algoritmos, estructura de datos y programacin orientada


a objetos. Bogota: Ecoe Ediciones. Primera edicin 2005.

Gueregueta Garcia ,Rosa y Vallecillo Moreno, Antonio.Tcnica de diseo de


algoritmos Universidad de Malaga.

Vctor Valenzuela Ruz. Manual de anlisis y diseo de algoritmos. 2003 de


Instituto Nacional de Capacitacin

Docente: Ing. Erech Ordoez Ramos


Pg. 33