Beruflich Dokumente
Kultur Dokumente
Un mismo problema puede resolverse con distintos algoritmos, por ejemplo la ordenacin de
un vector. Los criterios ms relevantes para determinar qu algoritmo de los que resuelven el
mismo problema es mejor, son los siguientes:
a) que el algoritmo sea fcil de entender, codificar y depurar: es uno de los criterios
ms relevantes en la actualidad, pues estas caractersticas reducen el tiempo de
programacin, y por tanto el coste del desarrollo y mantenimiento.
b) que el algoritmo sea eficiente en cuanto a los recursos de memoria que consume
para guardar datos e instrucciones durante su ejecucin, es decir, es deseable que
consuma pocos recursos.
c) que sea eficiente en cuanto al tiempo, es decir, que tarde el menor tiempo posible.
Suponiendo que el primer criterio se cumple en los algoritmos a comparar para determinar
cul de ellos es mejor, y dado que el uso eficiente de la memoria es menos crtico, pues esta
puede ampliarse fcilmente, vamos a estudiar qu algoritmo es mejor desde el punto de vista
del tiempo de ejecucin que consume. A mayor tiempo de ejecucin diremos que el algoritmo
es ms complejo o que tiene mayor complejidad.
Calcular si un algoritmo consume menos tiempo que otro, puede hacerse de dos formas:
a) empricamente o a posteriori: se ejecuta el programa y se mide el tiempo que tarda,
por ejemplo leyendo la hora del computador al principio y al final del algoritmo
(introduciendo sendas instrucciones dentro del programa) y despus de ejecutarse,
restndolas. Los inconvenientes de este mtodo son que no se prueban todos los
ejemplares posibles de datos de entrada y que se pierde tiempo implementando
varios algoritmos para luego seleccionar slo el mejor.
b) tericamente o a priori: se calcula matemticamente y sirve para todos los datos de
entrada, incluso para conjuntos muy grandes de datos a procesar. Por tanto es el
mtodo ms adecuado y el que vamos a aprender. La complejidad respecto del
tiempo de un algoritmo se va a determinar en funcin del nmero N de elementos a
procesar (o ms concretamente, de operaciones de procesamiento). N se denomina
el tamao de los datos de entrada (o tamao de la entrada). En definitiva, vamos a
aprender a calcular el tiempo que tarda un algoritmo en funcin del tamao de
la entrada, que es una funcin a la que llamaremos T(N), cuyo valor es el
coste en tiempo del algoritmo cuando la entrada es de tamao N.
A continuacin se dan algunos ejemplos de algoritmos, indicando para cada uno de ellos, cul
es el significado del tamao de la entrada N:
___________________________________________________________________
1
Ana Beln Moreno Daz
Ejemplos:
En los siguientes ejemplos se puede ver que el significado de N depende del tipo de problema a resolver por el
algoritmo. N es el nmero de datos a procesar por el algoritmo o el nmero de operaciones realizadas para el
procesamiento de los datos del algoritmo. N es aquello que cuando es grande, el algoritmo tardar mucho tiempo
en ejecutarse, y cuando N es pequeo el algoritmo tardar poco tiempo. Por tanto, el tiempo de ejecucin del
algoritmo T(N), se calcular como una funcin de N:
a) Saber si un nmero N es par o impar restndole 2 repetidamente mientras el resultado sea mayor que 1
y finalmente comprobando el valor del resto. El nmero de operaciones depender de N, ya que habr
que realizar N/2 restas. El nmero de pasos depende de N, por tanto, el valor del dato de entrada N es
el tamao de la entrada en este algoritmo, ya que a mayor N habr ms restas y por tanto ms datos a
procesar.
b) Buscar un elemento en un array unidimensional de N elementos: N es el tamao de la entrada, es el
nmero de datos a comparar con el nmero buscado.
c) Ordenar un array de N elementos: en este caso, N es el tamao de la entrada, es el nmero de datos que
al variar hace que el algoritmo tarde ms o menos, es de lo que depende el tiempo de ejecucin.
d) Invertir el orden de los dgitos de un nmero natural:
(4351,0)->(435,1)->(43,15)->(4,153)->(0,1534)
El tiempo que tarda el algoritmo depende de la longitud N del nmero que hay que invertir. Por tanto,
dicha longitud N es el tamao de la entrada en este algoritmo.
e) Sumar las componentes de un vector de nmeros reales: el tamao de la entrada N es el nmero de
componentes del vector.
f) Suma lenta de dos nmeros naturales a y b:
Se ejecutan b iteraciones => el tamao de la entrada N es el valor del dato de entrada b, pues el nmero
de pasos o iteraciones depende de b.
_____________________________________________________________________
As, para un vector se suele utilizar como variable N su longitud; para una matriz, el nmero
de elementos que la componen; en un fichero, se suele usar el nmero de registros que hay
que leer o escribir, etc.
Por ltimo, hay que distinguir entre el coste de tiempo T(N) de un algoritmo en el caso peor
y el coste de tiempo en el caso mejor. T(N) en el caso peor es el tiempo mximo que un
algoritmo puede necesitar para una entrada de tamao N, mientras que T(N) en el caso mejor,
expresa el tiempo mnimo que el algoritmo puede necesitar para una entrada N.
____________________________________________________________________
Ejemplo:
Sea el algoritmo de bsqueda secuencial de un elemento en un array o en una lista ordenada crecientemente de
longitud N. Se recorre el vector ordenado desde el primer elemento hasta encontrar el elemento buscado o hasta
encontrar uno mayor. El tamao de la entrada del que depende el nmero de pasos, es la longitud N de la lista.
a) El caso mejor para la ejecucin del algoritmo se da cuando el primer elemento es mayor o igual al
elemento buscado. En este caso el tiempo consumido por el algoritmo es el mnimo para una
entrada N, pues se ejecutar un nico paso. Dicho tiempo ser constante al no depender de N.
b) El caso peor se da cuando se alcanza el tiempo mximo para una entrada de tamao N, y en este
ejemplo se produce cuando el ltimo elemento del array es menor o igual que el elemento buscado
y por tanto hay que recorrer el vector hasta el final (N pasos o comparaciones). Este tiempo
mximo s depende de N.
_____________________________________________________________________
2
Ana Beln Moreno Daz
Para analizar la complejidad de un algoritmo vamos a tener en cuenta slo el caso peor, es
decir, calcularemos T(N) siempre para el caso peor. Este ser el tiempo mximo que
tardar el algoritmo para una entrada de tamao N, y es el que se utilizar para comparar cul
de los algoritmos es mejor, sin importar el tiempo que tardan en casos mejores. Cuando se
requiere que el problema se resuelva en un tiempo limitado, puede asegurarse que esta medida
no se superar.
Por ltimo, hay que sealar que dos implementaciones distintas de un mismo algoritmo (por
ejemplo escritas en diferentes lenguajes de programacin o ejecutadas en diferentes mquinas
o programados por distintos programadores), no diferirn en su coste (eficiencia) en ms de
alguna constante multiplicativa c.
____________________________________________________________________
Ejemplo:
As, calcularemos la eficiencia en tiempo mediante T(N) en el caso peor, salvo una
constante multiplicativa, pudiendo variar esta constante segn el lenguaje, etc.
(a) N (b) N
Figura 1. (a) Las diferencias de T(N) son menos significativas para datos de tamao pequeo. (b) Las diferencias
de T(N) se hacen muy significativas a medida que N crece.
3
Ana Beln Moreno Daz
El tipo de funcin de que se trata T(N), representa cul ser el comportamiento para datos de
gran tamao.
Una medida del comportamiento asinttico de T(N) es una cota superior de T(N).
Dicha cota de T(N) es una funcin que sirve de cota superior cuando el argumento N tiende a
infinito. Usualmente se utiliza la notacin O (llamada notacin O grande o notacin O
mayscula) sirve para referirse al conjunto de funciones acotadas superiormente por una
funcin c.g(N), es decir: O(g(N)) es el conjunto de funciones acotadas por c.g(N),
siendo c +.
Significa que T(N) tiene un comportamiento asinttico tal que no crece ms deprisa que
alguna funcin proporcional a g(N) => c.g(N) acota el crecimiento de T(N), es decir
c.g(N) acota a T(N).
Denotaremos el coste de un algoritmo mediante O(g(N)). De todas las g(N) que acoten
superiormente a T(N) tomaremos la menor de ellas.
____________________________________________________________________
Ejemplo:
Supongamos que T(N) O(N), es decir que T(N) est acotada superiormente por c*N para alguna
constante c. Entonces, tambin cumplir que T(N) O(N2), y que T(N) O(N3), etc, es decir, est
acotada superiormente tambin por c*N2 , por c*N3, etc Entre todas las funciones que acotan a T(N),
siempre nos quedaremos con la cota mnima, es decir, diremos que T(N)O(N).
____________________________________________________________________
Las g(N) que aparecen ms frecuente ordenadas de menor a mayor crecimiento son:
As, un algoritmo con coste logartmico tiene escasa complejidad o consume poco tiempo de
ejecucin, y es por tanto un algoritmo eficiente. Sin embargo, un algoritmo con un coste
exponencial o con un coste factorial es un algoritmo que consume excesivo tiempo, tanto que
si el tamao de la entrada es elevado se dice que son algoritmos intratables, pues slo
permiten tamaos de la entrada pequeos. Fjese en la Figura 1 lo rpido que crece el tiempo
4
Ana Beln Moreno Daz
Una vez descritos los conceptos tericos necesarios para comprender el significado de la
complejidad de un algoritmo (en cuanto al coste en tiempo), expresada mediante la notacin
O grande, vamos a aprender a hallarla de forma prctica mediante unas reglas sencillas.
Las operaciones con datos simples (p.e. enteros, reales, caracteres, booleanos), as como
las instrucciones que procesan un dato simple, se ejecutan en un tiempo T(N) =
constante, lo que significa que el tiempo que tardan no depende del tamao de la entrada
N. Son instrucciones y operaciones con coste de tiempo constante las siguientes:
- Operaciones aritmticas (suma, resta, producto o divisin) de variables simples o de
tamao constante que no depende de N (p.e.: a + 7),
- Comparacin de datos simples (p.e. a < 3),
- Asignacin de un valor a una variable simple p.e. entera, real, etc. (p.e. c = 6;),
- Lectura y escritura de datos simples a travs de la E/S estndar o de fichero (p.e.
read, write),
- Acceso a una componente de un array, a un campo de un registro, o a la siguiente
posicin de un archivo (p.e. a[i] )
Si el coste T(N) es constante, es decir, si es siempre el mismo independientemente del
tamao de la entrada (es decir, no depende de N), entonces se tiene que:
Para calcular el tiempo T(N) de una secuencia de instrucciones se halla el coste de tiempo
de cada instruccin por separado, se suman estos costes y se aplican unas reglas para obtener
O(g(N)).
5
Ana Beln Moreno Daz
__________________________________________________________________________________
Ejemplo:
Sea un algoritmo dado por la secuencia de cuatro instrucciones:
I1;
I2;
I3;
I4;
Sean las instrucciones I1, I2,, In en secuencia con funciones de coste de tiempo
TI1(N),TI2(N),,TIn(N) en el caso peor respectivamente, y sean TI1(N)O(g1(N)),
TI2(N)O(g2(N)), , TIn(N)O(gn(N)) => el coste de la secuencia es:
Es decir, se suman todas las funciones de coste de tiempo de todas las instrucciones, pero de
los sumandos, para calcular g(N) slo se tiene en cuenta el de mayor orden (el que tiene
mayor crecimiento asinttico). Este trmino es el que ser el dominante sobre todos los dems
para N grandes.
_____________________________________________________________________
Ejemplo:
Ejemplo:
Ejemplo:
Las funciones polinmicas tienen un coste despreciable respecto de los trminos exponencial y factorial para N
grandes.
Ejemplo:
Sean las variables enteras longitud y a, sea la variable booleana vacia y el array de enteros lista.
La siguiente secuencia de instrucciones simples,
1) longitud = 0; // T1)(N) = cte => T1)(N) O(1)
2) lista[longitud] = 0; // T2)(N) = cte => T2)(N) O(1)
3) a = longitude + 1; // T3)(N) = cte => T3)(N) O(1)
4) vacia = true; // T4)(N) = cte => T4)(N) O(1)
5) return vacia; // T5)(N) = cte => T5)(N) O(1)
tiene el siguiente coste:
T(N) = T1)(N)+T2)(N)+T3)(N)+T4)(N)+T5)(N)=cte; T(N)O(max(1,1,1,1,1)) = O(1)
____________________________________________________________________
6
Ana Beln Moreno Daz
Puesto que slo se ejecuta uno de los bloques y queremos calcular el coste de tiempo en el
caso peor, consideraremos que se ejecutar el bloque ms costoso. As, el coste de una
instruccin de seleccin en el caso peor es el mayor de los costes de los bloques de sentencias
entre los que se selecciona la ejecucin de uno u otro. En general, dada una instruccin IF,
IF (condicin) THEN
bloque1
ELSE
bloque2
END;
switch (expresin) {
case valor1: bloque1;
break;
...
T(N)=max(Tbloque1(N),...,TbloqueL(N))O(max(gbloque1(N),..,gbloqueL(N)))
7
Ana Beln Moreno Daz
El coste de tiempo T(N) de un bucle es la suma del tiempo que tarda cada iteracin. Dada la
siguiente instruccin de repeticin que repite la ejecucin del bloque desde que una variable
entera i vale 1 hasta que vale N (en ambos casos inclusive), e incrementndose tras cada
iteracin en una unidad, en java :
FOR i:=1 TO N DO
bloque;
El nmero de veces que se repite la ejecucin del bloque anterior es N. Si el tiempo del bloque
es Tbloque(N) es el mismo en todas las iteraciones (es decir, es constante en cada iteracin
por no depender de i), el coste del bucle es Tbloque(N) multiplicado por el nmero N de
veces que se repite su ejecucin:
N N
T(N) = T i 1
bloque ( N ) Tbloque ( N ) 1 Tbloque ( N ) N
i 1
Observe que se puede sacar Tbloque(N) del sumatorio debido a que no depende de i, es igual
para todas las iteraciones. Los tiempos de las operaciones de control del bucle (asignacin,
comparacin e incremento) se omiten por ser de orden 1 (menor o igual al del bloque).
N
Por otro lado, el sumatorio 1 1 1 ...1 N , donde se ha sumado N veces 1.
i 1
______________________________________________________________________
Ejemplo:
Dado el siguiente bucle donde i y x son dos variables enteras, en el que aparecen enumeradas las instrucciones
empezando desde las ms internas hacia las ms externas:
2) FOR i:= 1 TO N DO
1) x := x+1;
A continuacin se calculan los tiempos de cada una desde las ms internas a las ms externas. El tiempo de la
instruccin de asignacin 1) es:
T1)(N) = cte O(1), y no depende de la iteracin i, es decir, es el mismo en todas las repeticiones.
T1)(N) = cte.
T2)(N) = cte.
T3)(N) = N.cte O(N)
__________________________________________________________________________________
8
Ana Beln Moreno Daz
Se analizan desde los ms internos hacia los ms externos. Cuando el cuerpo de un bucle
interno dentro de otro bucle tiene coste constante, es decir, cuando es el mismo en todas las
repeticiones, el tiempo del bucle externo se calcula multiplicando el tiempo del bloque interno
por el nmero de repeticiones de cada FOR.
____________________________________________________________________
Ejemplo:
Clculo de la complejidad en notacin O del siguiente bucle anidado:
N N N N
T(N) = cte cte N cte.N .1 cte.N .N O( N 2 )
i 1 j 1 i 1 i 1
_____________________________________________________________________
Ejemplo:
1) x := x+1;
2) FOR i:= 1 TO N DO
x := x+1;
3) FOR i:= 1 TO N DO
FOR j := 1 TO N DO
x:= x+1;
T1) (N) O(1)
T2) (N) O(N)
T3) (N) O(N2)
Tsecuencia (N) = T1)(N)+ T2)(N)+ T3)(N)= cte + cte.N + cte.N2 O(max(1,N,N2))
_____________________________________________________________________
Si el cuerpo o bloque de un bucle tarda un tiempo que vara en cada iteracin (es decir, dicho
tiempo depende de i, es funcin de i), no puede sacarse del sumatorio. El tiempo del
bucle se calculara as:
N
T ( N ) O Tbloque (i )
i 1
_____________________________________________________________________
9
Ana Beln Moreno Daz
NOTA: en el clculo de la complejidad, cuando el interior de un sumatorio depende de la variable del sumatorio
i, es til el uso de estas frmulas:
1 1 1 ... 1 N
i 1
N
N ( N 1)
i
i 1 2
O( N 2 )
N
N ( N 1)( 2 N 1)
i
i 1
2
6
O( N 3 )
...
N
i
i 1
k
O ( N k 1 )
N
N ( N 1) (N 2 N )
N
T3)(N) =
i 1
cte.i cte. i cte.
i 1 2
cte
2
O(N2), es cuadrtico.
____________________________________________________________________
max n iter
T(N)= Ti 1
bloque (i )
El tiempo de la comparacin se omite por ser O(1), es decir, por ser menor o igual que el del
cuerpo del WHILE.
_____________________________________________________________________
10
Ana Beln Moreno Daz
Ejemplos
1) i = 1;
2) | while (i N) {
| 3) x = x +1;
| 4) i = i+2
| }
Para calcular T2)(N), en primer lugar hay que calcular el nmero de repeticiones. Llamemos k al nmero de
repeticiones que hay que calcular, y lo expresaremos como una funcin de la variable N, que es la variable en la
que hay que escribir T(N): la variable i aumenta de 2 en 2 empezando en 1 hasta llegar a N => el while se
repite N/2 veces => k = N/2.
n/2 n/2
n
T2)(N) = i 1
cte cte
i 1
1 cte O ( N )
2
Tsec uencia ( N ) T1) ( N ) T2 ) ( N ) 1 N O(max(1, N ))
Tsec uencia ( N ) O( N )
____________________________________________________________________
Ejemplo:
Dada la siguiente secuencia de instrucciones:
1) x = 1;
2) | WHILE (x N) {
| 3) x = x*2;
| }
Para calcular T2)(N) es preciso calcular cuntas veces se repetir el bucle. Llamemos k al nmero de
repeticiones. Una vez que conozcamos k, el tiempo del WHILE se calcular as: T2) (N) = cte*k.
Puesto que T2)(N) es una funcin de N, se sustituiremos k expresado en funcin de N:
N iteracin valor de x (coincide con N tras la ltima iteracin, cuando se cumple la condicin del while)
1 2
2 4
3 8
4 16
5 32
6 64
. .
. .
k (ltima iteracin) 2k = N
Se expresa la funcin T(N) como una funcin matemtica donde aparecen dos casos: el caso
base y el caso recurrente. En el caso recurrente aparece una expresin en la que de nuevo se
encuentra la funcin T( ) por ser recursiva, con un tamao de la entrada menor que N, para
que en algn momento se terminen las llamadas recursivas.
Para calcular la complejidad de las funciones recursivas a partir de esta funcin matemtica,
se resuelve la ecuacin de recurrencias: consiste en encontrar una expresin no recursiva para
la funcin T(N). Para ello, se sustituyen las recurrencias por su igualdad hasta llegar a caso
base.
____________________________________________________________________
Bibliografa
- C. Pareja Flores y otros, Desarrollo de algoritmos y tcnicas de programacin, ed.: Ra-Ma, 1997.
- M.A. Weiss, Estructuras de Datos y Algoritmos, Addison-Wesley Iberoamericana, 1995.
- G. Brassard y P. Bratley, Fundamento de Algoritmia, Prentice Hall, 1997.
12