• No se han encontrado resultados

LA EFICIENCIA DE LOS ALGORITMOS

N/A
N/A
Protected

Academic year: 2021

Share "LA EFICIENCIA DE LOS ALGORITMOS"

Copied!
20
0
0

Texto completo

(1)

1 TEMA 1

LA EFICIENCIA

DE LOS

ALGORITMOS

INDICE

! " #$%

2 # " #

&' ( )*+ &" (+, +-%+

La eficiencia de los algoritmos

!"#$%

.

'

'/

'

0112

%'3

'

&'()*

4$4$567 +, +./58 99: 6+!+) .!,99; # BIBLIOGRAFÍA COMPLEMENTARIA

La eficiencia de los algoritmos

A.V. Aho, J.E. Hopcroft, J.D. Ullman: “The design and analysis of computer algorithms”. Addison-Wesley, 1974.

A.V. Aho, J.E. Hopcroft, J.D. Ullman:

“Estructuras de datos y algoritmos”. Addison-Wesley Iberoamericana, 1988.

S. Sahni: “Concepts in Discrete Mathematics”. The Camelot Publishing Company, 1985.

(2)

5

Normalmente, un problema se puede resolver por métodos distintos, con distintos grados de

eficiencia. Ejemplo: búsqueda de un número en

una guía telefónica.

Cuando se usa un ordenador es importante limitar el consumo de recursos.

Recursos: Tiempo:

Aplicaciones informáticas que trabajan “en

tiempo real”: requieren que los cálculos se

realicen en el menor tiempo posible.

Aplicaciones que manejan un gran

volumen de información: si no se tratan

adecuadamente pueden necesitar tiempos impracticables.

Problemas intrínsecamente complejos. Espacio: Las máquinas tienen una memoria

limitada.

6

COSTE = Consumo de estos recursos por parte de un algoritmo.

En esta asignatura nos interesa el estudio del coste temporal.

Si un programa se va a usar una o muy pocas veces, puede darse el caso de que lo más importante sea que sea fácil de entender, codificar y depurar.

A medida que se dispone de ordenadores más rápidos, se pretende resolver problemas más grandes y complejos, por lo que el uso de algoritmos eficientes sigue siendo importante.

La eficiencia de los algoritmos FACTORES DE LOS QUE DEPENDEN LOS PARAMETROS DEL COSTE:

A - Factores propios del problema:

procedimiento de resolución del problema, y los datos.

B - Factores dependientes de la máquina:

tipo de computador, lenguaje de programación, carga del sistema, etc.

En esta asignatura nos interesan los factores propios del problema.

La eficiencia de los algoritmos APROXIMACIONES AL ANÁLISIS DE LA EFICIENCIA DE LOS ALGORITMOS (memoria y tiempo de ejecución):

Análisis experimental o "a posteriori" (se verá en la prácticas de laboratorio). Consiste en ejecutar casos de prueba, haciendo medidas para:

una máquina concreta, un lenguaje concreto, un compilador concreto y datos concretos.

Análisis teórico o "a priori" (se verá en las clases teóricas). Consiste en obtener una expresión que indique el comportamiento del algoritmo en función de los parámetros que influyan. Interesante porque:

La predicción del coste puede evitar una implementación posiblemente laboriosa. Es aplicable en la etapa de diseño de los

algoritmos, constituyendo uno de los factores fundamentales a tener en cuenta.

(3)

9

COMPLEJIDAD (O COSTE) DE UN ALGORITMO:

Es una medida de la cantidad de recursos (tiempo, memoria) que el algoritmo necesita.

La complejidad de un algoritmo se expresa en función del tamaño o talla del problema.

TALLA DE UN PROBLEMA:

Es cualquier parámetro en función del cual se pueda expresar la complejidad del problema:

Nº de datos de entrada Nº de datos de salida

Valor de las variables numéricas Una función de los anteriores

Suele guardar relación con el volumen de los datos a tratar, y por ello se le suele llamar “tamaño” del problema.

10

EJEMPLOS:

1.- Algoritmo de ordenación: la talla del problema será el número de elementos a ordenar.

2.- Algoritmo de búsqueda de un elemento en una secuencia: la talla del problema será el número de elementos de la secuencia.

3.- Algoritmo del cálculo del factorial de un número: la talla será el valor del número.

¿COMO CALCULAR LA COMPLEJIDAD

TEMPORAL DE UN ALGORITMO?

Contando el número de operaciones elementales o pasos de programa que realiza.

De esta forma:

coste(n) = Número de pasos de programa en función de n.

Es independiente de la máquina concreta utilizada.

La eficiencia de los algoritmos

Son aquellas cuyo tiempo de ejecución está acotado superiormente por una constante que no depende de la talla del problema.

EJEMPLOS DE PASOS DE PROGRAMA:

x := y + z

1 paso

x := y + z x := x * x

2 pasos (ó también 1 paso)

si x = 0 entonces y := y + 1 sino

y := y - 1 fsi

1 paso (ó también 2 pasos)

si x = 0 entonces y := y + 1 fsi

1 paso

La eficiencia de los algoritmos

EJEMPLOS DE COSTES:

x := x + y

coste = 1 paso.

para i := 1 hasta n hacer x := x + y

fpara

talla = n, coste(n) = n pasos.

para i := 1 hasta n hacer para j := 1 hasta n hacer x := x + y

fpara fpara

(4)

13

GRÁFICAS DE FUNCIONES

14

TABLA DE TIEMPOS DE EJECUCIÓN

Tiempos de ejecución en un máquina capaz de ejecutar 109 pasos de programa por segundo para tallas (n) y costes (en número de pasos) dados.

n (Talla) Pasos 1 8 32 103 106 109 log2n < 1 ns 3 ns 5 ns 10 ns 20 ns 30 ns n 1 ns 8 ns 32 ns 1 s 1 ms 1 s nlog2n < 1 ns 24 ns 160 ns 10 s 20 ms 30 s n2 1 ns 64 ns 1 s 1 ms 17 min 38 años n3 1 ns 512 ns 33 s 1 s 38 años > 1010 años 2n 2 ns 256 ns 4.3 s > 10291 años > 10300K años > 10300M años n! 1 ns 40 s > 1018 años > 102K años > 105M años >109000M años nn 1 ns 17 ms > 1031 años >103K años > 106M años >109000M años Problemas inabordables

La eficiencia de los algoritmos TALLAS PARA DOS ORDENADORES DE

DIFERENTE POTENCIA

Talla (n) del problema que puede ejecutarse en un tiempo prefijado, en función de la velocidad del computador (que aumenta de V a 10V).

Nº de

pasos n para V n para 10V

n para 10V n para V 300 log2n 10 1010 109 100 n 10 100 10 5 n2 14 45 3.2 n3 / 2 12 27 2.3 2n 10 13 1.3 n! / 100 9 10 1.1 nn / 100 7 7 1

A medida que se baja en la tabla, aumenta más despacio la talla del problema que es posible tratar usando una máquina 10 veces más rápida.

Cuando el coste es lineal (100 n en esta tabla) una máquina 10 veces más rápida permitirá tratar un problema 10 veces “más grande”.

La eficiencia de los algoritmos

¿De qué depende la complejidad de un

algoritmo A?

1. De la talla del problema: n.

2. Para una talla fija, de la instancia del problema.

En general obtendremos una expresión del coste distinta para cada instancia:

costeA(I,n) =

Número de pasos de programa para una talla n y una instancia I

Nos interesan las instancias significativas: Ip: peor de los casos. Cuando son

necesarios el máximo número de cálculos.

Im: mejor de los casos. Cuando son necesarios el mínimo número de cálculos.

(5)

17

Sean:

n la talla del problema de A

S(n) = { I : I Instancia talla(I) = n } entonces:

costeAp (n) = máx {costeA(I,n) : I S(n)}

= costeA(Ip,n) (coste peor) costeA m (n) = mín { costeA(I,n) : I S(n)} = costeA(Ip,n) (coste mejor)

costeAMed (n) = S(n) P(I) * costeA(I,n)

(coste medio)

18

EJEMPLOS DE INSTANCIAS

1.- Búsqueda secuencial de un elemento x en un vector a:

función buscar

( x: elemento;

a: vectoríndice de entero; n: índice)

devuelve índice;

{1n k:1kn:ak=x} var i:índice fvar; i:=1;

mientras a[i]x hacer i:=i+1

fmientras; devuelve i

{1in ai=x j:1j<i:a[jx} ffunción

• Talla del problema: n. • Instancias:

x Caso mejor

x Caso genérico

x Caso peor

La eficiencia de los algoritmos

2.- Búsqueda del máximo de un vector a:

función máximo(a: vector; n: índice) devuelve entero;

{ 1n }

var max:elem; i:índice fvar; i:=2;

max:=a[1];

mientras i<n hacer

si a[i] > max entonces max := a[i ] fsi; i := i + 1 fmientras; devuelve max { (j:1jn:a[jmax) (j:1jn:a[j=max) } ffunción

• Talla del problema: n.

• No existen diferentes instancias significativas (en cualquier caso se recorre todo el vector).

La eficiencia de los algoritmos

Una forma alternativa de calcular la complejidad en el peor caso consiste en la identificación y seguimiento de una instrucción crítica. La instrucción crítica de un algoritmo es la

instrucción (o comprobación) que más veces se ejecuta independientemente de casos.

Si es posible identificar una instrucción crítica en un algoritmo, el coste se puede calcular como el número de veces que se repite esta instrucción.

Ejemplo: en el algoritmo de búsqueda del mínimo podríamos tomar la instrucción Si_entonces ya que es la instrucción que más veces se ejecuta (n-1 veces)

(6)

21

Determinar exactamente costeA p y coste A

m

puede resultar difícil;

no tiene mucho sentido si hablamos de pasos de programa;

puede resultar excesivamente laborioso si sólo necesitamos calcular la complejidad de un algoritmo para compararlo con otros durante la fase de diseño, antes de conocerlo en detalle.

22

Ejemplos:

Sean A y A' dos algoritmos que resuelven el mismo problema.

Si costeA (n) = 2n y costeA' (n) = 3n, podremos

decir que A y A' tienen una eficiencia parecida. Si costeA(n) = 2n y costeA' (n) = 100n, A será

más eficiente que A'. Pero el uso de un ordenador suficientemente rápido para ejecutar A’ haría que este algoritmo se ejecutase siempre en menos tiempo que A en el ordenador original. Por lo tanto, los avances tecnológicos podrían justificar el uso de A’ si éste poseyera suficientes ventajas secundarias sobre A.

Si costeA(n) = n2 y costeA' (n) = 3n, podremos

decir que:

A es más eficiente que A’ para n = 1, 2; A y A’ son igual de eficientes para n = 3; A’ es más eficiente que A para n > 3.

La eficiencia de los algoritmos

CONSIDERACIONES:

Interesa estudiar el comportamiento de un algoritmo para tallas relativamente grandes:

complejidades asintóticas.

Interesa comparar los comportamientos de los algoritmos según el orden de magnitud de sus complejidades.

Interesa hacer estudios de la complejidad

independientes de la velocidad del computador donde se programa el algoritmo

desarrollado. Esto significa que funciones de complejidad que difieren en un factor constante se consideran idénticas a efectos de medidas de costes.

Por lo tanto, para el cálculo de la complejidad adoptaremos un CRITERIO ASINTOTICO.

La eficiencia de los algoritmos

/

/

0

0

Objetivo: obtener una notación clara y simple para expresar el coste de un algoritmo para valores grandes de la talla y con independencia de la velocidad del ordenador utilizado.

En lo que sigue, f, g, f1, f2, y f3 serán funciones de N

(7)

25

NOTACION O

Definición. Se dice que

- f es como mucho del orden de g, o que - f crece más lentamente o igual que g, o que - g es una cota superior de f,

sii c>0, n0 N: f(n) c g(n) nn0

Definición.

O(g(n)) = { funciones que son como mucho del orden de g(n) }

Ejemplos. 1.- 3n O(n): Si se toma C=3 y n0=0 se tiene f(n) = 3n 3n = C·g(n) n0. 2.- 3n O(n2 ): Si se toma C=3 y n0=0 se tiene f(n) =3n C·g(n) = 3n2n0. 26 NOTACION

Definición. Se dice que

- f es como mínimo del orden de g, o que - f crece más rápidamente o igual que g,

o que

- g es una cota inferior de f,

sii c>0, n0 N: c g(n) f(n) nn0

Definición.

(g(n)) = { funciones que son como mínimo del orden de g(n) }

Ejemplos. 1.- 3n (n): Si se toma C=1 y n0=0 se tiene C·g(n) = 1·n 3n = f(n) n0. 2.- n2 (3n): Si se toma C=1 y n0=3 se tiene C·g(n) = 1·3nn2 = f(n) n3.

La eficiencia de los algoritmos

NOTACION

Definición. Se dice que - f es del orden de g, o que

- f crece igual de rápidamente que g, o que

- g es una cota superior e inferior de f, sii

c,d>0, n0 N: c g(n) f(n) d g(n) nn0

Definición.

(g(n)) = { funciones que son del orden de g(n) }

!

!

Proposición. f(n) (g(n)) f(n) O(g(n)) f(n) (g(n)) f(n) (g(n)) f(n) O(g(n)) g(n) O(f(n)) Ejemplo. 3n (n), pues

a) 3n O(n) (visto anteriormente).

La eficiencia de los algoritmos

b) 3n (n) ( “ “ ). Definición. Se dice que

- f es de menor orden que g, o que - f crece más lentamente que g, sii

f(n) O(g(n)) pero f(n) (g(n)).

Definición. Se dice que - f es de mayor orden que g, o que - f crece más rápidamente que g, sii

f(n) (g(n)) pero f(n) (g(n)).

TEOREMA.

1- f es de menor orden que g sii O(f(n)) O(g(n)). 2- f es de mayor orden que g sii (f(n)) (g(n)).

(8)

29

Los siguientes teoremas son útiles para comparar tasas de crecimiento de funciones.

TEOREMA limf n g n K n ( ) ( ) 0 (f(n)) (g(n)) (f y g son del mismo orden).

TEOREMA

lim f n g n

n

( )

( ) f(n ) crece más rápidamente que g(n), o lo que es lo mismo: O(g(n)) O(f(n)).

TEOREMA

lim f n g n

n

( )

( ) 0 g(n ) crece más rápidamente que f(n). o lo que es lo mismo: O(f(n)) O(g(n)).

30 COROLARIO

a. Si p es un polinomio de grado r, entonces p es del mismo orden que nr.

b. n , con >1 constante, crece más rápidamente que cualquier polinomio. c. Si 1>K2>1, entonces

n crece más rápidamente que n, pero

log(n) es del mismo orden que log(n). d. Cualquier polinomio crece más rápidamente

que log(n).

e. n! crece más rápidamente que n.

f. nn crece más rápidamente que n!.

La eficiencia de los algoritmos

"

"

Muchas veces las notaciones asintóticas pueden aparecer dentro de expresiones, por ejemplo:

f(n ) = n2 + O(1/n)

significa que f(n ) es una función cuadrática más un término asintótico menor que 1/n. Se debe de entender como suma de conjuntos de funciones.

f(n ) n2

+ O(1/n)

#$%

COROLARIO

a) De menor a mayor orden:

O(1) O(log(n)) O(n) O(nlog(n)) O(n2)O(n3) ... O(Kn) O(n!) O(nn). b) De mayor a menor orden:

(1) (log(n)) (n) (nlog(n)) (n2 ) (n3 ) ... (Kn ) (n!) (nn ).

La eficiencia de los algoritmos

&1&%#"#"2(&

Para calcular el coste de un algoritmo:

En primer lugar hay que determinar la talla del algoritmo.

En los algoritmos en los que el coste temporal sea independiente de las instancias, es decir, cuando el caso mejor y el peor coincidan, utilizaremos directamente la notación para estimar la complejidad del algoritmo:

coste (n) (f(n)).

En los algoritmos en los que el coste temporal varíe en función de las instancias, podremos distinguir:

Peor caso y Mejor caso.

(9)

33

PEOR CASO:

Utilizaremos la notación (o la si fuera necesario) para estimar la complejidad del algoritmo en el peor de los casos:

costep (n) (f(n)),

con lo que obtendremos una cota superior de la complejidad del algoritmo:

costeA(n) (f(n)).

MEJOR CASO:

Utilizaremos la notación (o la si fuera

necesario) para estimar la complejidad del algoritmo en el mejor de los casos:

costeAm (n) (g(n)),

con lo que obtendremos una cota inferior de la complejidad del algoritmo:

costeA(n) (g(n)).

34

EJEMPLOS.

1. Para el algoritmo de búsqueda secuencial: • Talla del problema: n.

• Instancias significativas: caso mejor, caso peor. costep(n) (n) costem(n) (1) Por lo tanto: coste(n) (n) coste(n) (1)

2. Búsqueda del máximo de un vector: • Talla del problema: n.

• Instancias: no hay instancias significativas que afecten al coste. En cualquier caso se recorre todo el vector.

coste(n) (n).

La eficiencia de los algoritmos

#"131/"#%/"2&"!//

Procedimiento a seguir:

1. Determinar qué parámetro(s) nos da(n) la talla o tamaño del problema, en función de la cual se expresará la complejidad.

2. Identificar el caso peor y el caso mejor de comportamiento del algoritmo en cuanto a consumo de tiempo (o de espacio si se estudia la complejidad espacial).

3. Aplicar un método de obtención de las cotas de complejidad.

Complejidad Temporal: se calcula contando el

número de pasos de programa de cada instrucción en función de la talla del problema.

La eficiencia de los algoritmos

2&"!///"&%1%#(41"%

Vamos a estudiar la complejidad de las siguientes instrucciones:

operaciones básicas, secuencia de instrucciones, sentencia alternativa, y sentencia iterativa.

Operaciones básicas. Se van a considerar como pasos de programa las operaciones básicas: asignación, comparación, operaciones aritméticas, lectura/escritura...

Coste de un paso de programa (1)

Ejemplo. Las siguientes instrucciones tienen un

coste (1): x := y + z;

b := x y (a b);

(10)

37

Secuencia de instrucciones ( S = S1 ; S2).

coste( S ) = coste( S1 ) + coste( S2 )

Caso especial: para grandes tallas, puede darse que una de las instrucciones tenga coste despreciable frente a la otra, con lo que se podrá aplicar el siguiente resultado:

coste( S 1 ) ( f1 ) coste( S2 ) ( f2 ) coste( S ) ( f2 ) O( f1 ) O( f2 ) Ejemplos. 1. Supongamos que: coste( S1 ) = 2n + 3 (n), coste( S2 ) = 5n + 1 (n). Entonces coste( S1 ; S2 ) = 7n + 4 (n). 2. Supongamos que: coste( S1 ) = 3n + 1 (n), coste( S2 ) = 7n2 (n2). Entonces coste( S1 ; S2 ) (n2). 38

Sentencia alternativa “si .. fsi”.

Si B entonces S1 sino S2 fsi coste( “SI “ ) = coste( B ) + coste( S1 ó S2 ),

dependiendo de la acción (S1 ó S2) que se ejecute:

B cierta se ejecutará S1

coste( “SI” ) = coste( B ; S1 )

B falsa se ejecutará S2

coste( “SI” ) = coste( B ; S2 )

Si denotamos:

coste( B ) ( g ), coste( S1 ) ( f1 ),

coste( S2 ) ( f2 ),

en la práctica se suelen dar los siguientes casos:

Costes parciales coste( “SI” )

O( g ) O( f1 ) = O( f2 ) ( f1 )

O( g ) O( f1 ) O( f2 ) ( f1 ), O( f2 )

La eficiencia de los algoritmos

Sentencia iterativa “mientras ... fmientras”.

Mientras B hacer S fmientras

Sea n el número de iteraciones que de hecho se ejecutan la ejecución de la instrucción anterior será equivalente en efectos y en coste a la ejecución de:

1ª iteración nª iteración (falla B)

B ; S; ... B ; S; B

(Nota: B es una función y no un procedimiento, por lo que el cuadro anterior contiene una imprecisión.)

coste( “Mientras” ) = i = 1..n coste( B(i) ; S(i) ) + coste( B(i+1) )

donde (i) hace referencia a la i-ésima iteración.

Puesto que los costes parciales anteriores pueden ser distintos en cada iteración del bucle, la casuística que puede presentarse es muy variada.

La eficiencia de los algoritmos Casos Prácticos

Caso 1. Se realizan n iteraciones, y la i-ésima

iteración (guarda + cuerpo) tiene un coste ip, con p constante. Coste = i n p 1 n 2 (n ) p i 1 n p 1 p p 1 Coste (np+1 ) Ejemplo:

Para i := n decreciendo hasta 1 hacer escribe_letra(“a”, i)

fpara,

en donde escribe_letra(“a”, i) escribe i

veces el carácter “a” y tiene un coste (i). La talla del problema es n, y su coste será:

coste = ( 2) 1 n i n i

.

(11)

41

Son habituales los siguientes subcasos:

p = 0 1 ( ) 1 n n n i

. p = 1 (2 1) ( 2) 1 1 nn n i n i

. p = 2 ( 1)(62 1) ( 3) 1 2 nn n n i n i

.

Caso 2: Medidas logarítmicas.

Supongamos que en cada iteración la talla n se reduce en un factor c, hasta llegar a una talla mínima n0 >0 para la que se da la condición de salida del bucle.

Tras la 1ª iteración: la talla pasa a n/c Tras la 2ª " : " n/c2 ...

y tras una q-ésima iteración, la talla se reduce a n0.

Como se tendrá que n/ck = n0, el número de

iteraciones será:

k = logc (n/n0).

42

Ejemplo: búsqueda dicotómica en un vector

ordenado. { v está ordenado } procedimiento dicotómica (v: vector1..n de entero; n, x: entero; sal está: lógico; sal m: entero) es var i,j: entero fvar;

i:=1 ; j:=n; está := falso; repetir m := (i+j) div 2; opción v[m] > x: j := m - 1; v[m] < x: i := m + 1; v[m] = x: está := verdadero; fopción

hasta que i>j está fprocedimiento

{1mn((está vm=x)

(está k:1kn:vkx)}

• La talla del problema es la dimensión del vector. Se puede considerar la talla como un valor dinámico que tras cada iteración es la longitud de la zona del vector donde aún no se ha descartado que pueda estar x.

La eficiencia de los algoritmos Caso peor: x no está en el vector, y por lo tanto en

número de iteraciones es máximo.

costep(n) = 1 + coste_iteración

= 1 + (1 + coste_si + coste_guarda)*(nº iteraciones) = 1 + K*(nº iteraciones).

El cálculo del número de iteraciones en este caso es un ejemplo de reducción logarítmica.

Tras cada iteración se reduce la talla aproximadamente a la mitad, hasta llegar a un tamaño 1. Por ello, el número de iteraciones es log2n.Luego

costep(n) = 1 + Klog2n (log2n).

Caso mejor: se encuentra de inmediato el elemento

y la iteración cesa: costem(n) (1).

En resumen:

coste(n) O(log2n), coste(n) (1).

La eficiencia de los algoritmos

&

&

!

!

! ( <3' // ' - '

.

.

= (// >+

Definición del problema

!""# !""" $

(12)

45

: vector x entero x entero lógico

Para v1 vector, i,j entero

ordenado(v1) = (k: i k <j: v[k v[k+1 )

: vector x vector x entero x entero lógico Para v1,v2 vector, i,j entero

perm(v1,v2,i,j)= (k: i k j: (( t: i t j: v1[k=v2[t )

nveces(v1[k, v1,i,j) = nveces(v1[k,v2,i,j) ))

/: TipoBase x vector x entero x entero

entero

Para e TipoBase, v vector, i,j entero nveces(e,v,i,j) = k: i k j: igual (v[k,e)

': TipoBase x TipoBase {1,0}

Para x,y TipoBase igual(x,y)= 1 sii x=y

igual(x,y)=0 sii xy

46

Estrategia para la ordenación:

1.- Considerar el vector dividido en dos zonas:

- elementos que ya están ordenados - elementos por reubicar.

2.- Se utiliza una variable “i” para marcar el límite

entre ambas zonas.

INVARIANTE:

1 i-1 i n

k : 1 k < i - 1: v[k] v[k+1] 1 i 1 n

designa las posiciones que contienen elementos ordenados entre sí,

posiciones cuyos elementos no están necesariamente ordenados.

Función limitadora t = n - i + 1

La eficiencia de los algoritmos

Diseño del algoritmo a partir del

invariante:

- El invariante se cumple inicializando “i” a 2, ya que inicialmente el primer elemento está ordenado con respecto a si mismo 1 2 n En efecto, formalmente: k : 1 k < i - 1 : v[k]v[k+1] 1 i 1 n i = 2 k : 1 k < 1 : v[k] v[k+1] 1 1 n

La eficiencia de los algoritmos

Diseño del algoritmo a partir del

invariante:

- La iteración debe acabar cuando el vector esté totalmente ordenado. 1 n k : 1 k < n : v[k] v[k + 1] Por tanto: !B = (i = n + 1) B = ( i n)

(13)

49

Diseño del algoritmo a partir del

invariante:

- El cuerpo de la iteración, S, deberá conseguir que en cada pasada se reduzca la zona desordenada ó función limitadora, t = n -i +1

¿?

¡El problema es lo suficientemente complejo como para

que esta instrucción sea a su vez una iteración !

Las diferentes propuestas que se pueden hacer para S conducen a diferentes algoritmos de ordenación

50

RESUMEN:

Estructura algorítmica

general para la ordenación

P = {v = V} i:=2; mientras i n hacer S; i:=i+1 fmientras Q = {ordenado(V, 1, n) v = perm(V)} Invariante 1 i-1 i n Función limitadora t = n -i +1

La eficiencia de los algoritmos

Ordenación por inserción

El algoritmo de ordenación por inserción propone para S una iteración basada en la siguiente idea:

"se escoge el primer elemento de la zona por ordenar y se inserta en el lugar correspondiente en la zona ya ordenada"

i := 2;

mientras i n hacer

insertar ordenadamente v[i] en v[1..i-1];

i := i + 1 fmientras

La eficiencia de los algoritmos

Para insertar ordenadamente v[i] en v[1 .. i - 1]

1.- buscar secuencialmente la posición p

correspondiente a v[i] en v[1 .. i - 1].

2.- desplazar hacia la derecha todos los elementos

entre esta posición e i-1 inclusive, para situar v[i] en su emplazamiento definitivo.

i := 2;

mientras i n hacer

buscar la posición p correspondiente a v[i];

i n p 1 i-1 v[i] >v[i] 1pi { } x := v[i];

desplazar hacia la derecha todos los elementos de v[p .. i - 1]; v[p] := x; i n 1 i-1 { } i:=i+1 fmientras

(14)

53

¡los pasos 1 y 2 se pueden realizar de forma simultánea!

Reformulación en un paso de insertar ordenadamente v[i] en v[1 .. i - 1]

{i n ordenado(v, 1, i-1) v[1 .. i-1] = perm(V, 1, i-1)}

p:=i; x:=v[i]; mayor:=true;

mientras (p>1) mayorhacer

si v[p-1]<=x entonces mayor:=false sino v[p]:=v[p-1]; p:=p-1 fsi; fmientras; {p = 1 !(mayor)} v[p]:= x;

{(i n) ordenado(v, 1, i) v[1 .. i] = perm(V, 1, i)}

54

>?

@A

?

( B '% B@ C0D2 E = D? 02? ( B %3% B@ C0D2 E >F(@ >F(@ G >DF(@D?H @D?HD? 02? 1 1 ) 1 ( 1 1 i i j i i 1 ) ( 1

La eficiencia de los algoritmos

i := 2;

mientras i n hacer

insertar ordenadamente v[i] en v[1..i-1];

i := i + 1 fmientras

>?

( El vector está ya ordenado

coste(n) (n)

( El vector está ordenado al revés

coste(n) (n2)

( El vector está ya ordenado

C0D2 E F(@ >F(@ >F(@ G >DF(@0DA2?H @D@?HD?@

La eficiencia de los algoritmos

" 5insertar ordenadamente v[i] en

v[1..i-1],

67

02?

(/

/<

" 5insertar ordenadamente v[i] en

v[1..i-1],58 69 7 =F0?20/IJ/2 =F0?20/IJ/2 G =- 0?20/IJ@/2@

Ejercicio: Diseñar el algoritmo para insertar

ordenadamente v[i] en v[1 .. i - 1] utilizando búsqueda

binaria. En este caso, el método de ordenación se conoce

con el nombre de “Inserción binaria”. Compárese el diseño obtenido con el presentado anteriormente.

1 1 ) ( 1 1 n i n n

)

(

))

1

(

1

(

2

)

1

(

2 1 1

n

n

n

i

n i

67 =

(15)

57

Ordenación por selección

El algoritmo de ordenación por selección propone para S una iteración basada en la siguiente idea:

I =

1 i-1 i n

“Tras cada iteración, cualquier elemento de es menor o igual que cualquier elemento de

Esto es,

“se aumenta el tamaño de la zona ordenada situando en la posición “i” el mínimo de v[i .. n] ”

"k : 1 k < i-1 :v[k] v[k+1] 1 i n

m : 1< i m n : v[i-1] v[m]} t n - i + 1

58

Diseño del algoritmo a partir del

invariante:

- El invariante se cumple inicializando “i” a 1, para que pueda buscar el primer mínimo en el intervalo [1 .. n]

I =

1 n

- La iteración debe acabar cuando el vector esté totalmente ordenado. Recordemos que mínimo(v, n, n) =

v[n]

¡ el último elemento YA estará ordenado!

Por tanto, realizamos n-1 pasadas de ordenación y terminamos cuando i = n

!B = (i = n) ó B = ( i n -1)

- Para poder disminuir el tamaño de la zona desordenada, pos_min := mínimo(v, i, n);

x:= v[pos_mín]; v[pos_mín]:=v[i]; v[i]:=x; i:=i+1

La eficiencia de los algoritmos

donde mínimo(v,i,n):

algoritmo mínimo

(DATOS v:vector[1..n]de TipoBase; inicio,fin:1..n;

RESULTADOS p:inicio..fin) var siguiente:entero fvar

siguiente:=inicio+1; p:=inicio; mientras siguiente<=fin hacer

si v[siguiente]< v[p] entonces p:=siguiente; siguiente:=siguiente+1; fmientras devuelve p falgoritmo 0/2 mientras siguiente<=fin hacer

si v[siguiente]< v[p] entonces p:=siguiente; siguiente:=siguiente+1;

fmientras

Talla = fin - inicio +1=m

C0D2 E F( @ >F( @ G >DF( @0DA2?H @D@?HD? @

La eficiencia de los algoritmos

0 2?

algoritmo ordenar (DATOS v:vector[1..n]de TipoBase;

RESULTADOS v: vector [1..n] de TipoBase) var i:entero fvar

i:=1;

mientras i<n hacer p:=mínimo(v,i,n); intercambiar(v[i],v[p]); i:=i+1; fmientras falgoritmo Talla = n C0D2 E >F(@ >F(@ G >DF(@D? @D?D?@ " 5 . :6;5575 8 9 =F0?2 0/2 =F0?2 0/2@ G

1

1

)

(

1

m i

m

(16)

61 =- 0?@2 0/@2 02? " "

algoritmo ordenar (DATOS v:vector[1..n]de TipoBase; RESULTADOS v: vector [1..n] de TipoBase) var siguiente: entero fvar

para siguiente:=1 hasta n-1 hacer

para j:=n descendiendo hasta siguiente+1 hacer si v[j] < v[j-1] entonces intercambiar(v[j],v[j-1]) fsi fpara fpara falgoritmo K ( 02?

1

1 2 1 1

)

(

1

))

1

(

(

n i n i

n

i

n

i

n

1 1 1 1 1 1 1 1 ) 1 ( 1 n i n i n i n i j i n i n

)

(

1

2 1 1 1 1

n

i

n

n i n i

62

5.2- Otros algoritmos sobre vectores. 5.2.1La bandera nacional holandesa

Sea una fila de n bolas de color blanco, rojo y azul. Sea un brazo mecánico capaz de efectuar las operaciones:

• color(i): averigua el color de la bola que se encuentra en la posición i-ésima de la fila. • perm(i,j): permuta las bolas de estas

posiciones.

Se pide un algoritmo iterativo que en una sola pasada sobre la fila, realizando como mucho n intercambios, y sin utilizar una fila auxiliar, deje a las bolas formando la bandera nacional holandesa.

1. ESPECIFICACION.

Precondición: la fila está constituida únicamente por

bolas rojas, blancas y azules, dispuestas en cualquier orden.

1 n

?

Postcondición:

1 n

azul blanco rojo

en donde alguna de las zonas puede estar vacía.

La eficiencia de los algoritmos

2. INVARIANTE.

En un estado intermedio cualquiera, en la fila

-Hay tres bandas formadas por bolas ya revisadas y situadas en una posición adecuada.

-Entre unas posiciones “v” y “x” está una banda

indefinida formada por aquellas bolas que aún no se

han revisado.

-El color de cualquier bola de la fila es blanco, rojo o azul.

Si se indica con la zona indefinida:

r ?

u v x

1 n

Invariante:

i:1iu:color(i)=azul j:u<j<v:color(j)=blanco

k:x<kn:color(k)=rojo vx+1

Nótese que:

Los estados inicial y final aparecen como casos particulares de este invariante. En el estado inicial, las bandas de colores están vacías, y la zona indefinida

La eficiencia de los algoritmos

coincide con toda la fila. En el estado final, la zona indefinida está vacía.

3a) El invariante se cumple al empezar la iteración si se

inicializa:

u:=0; v:=1; x:=n

u v x

0 1 n

3b) Para que se cumpla la postcondición, en el

invariante se tiene que dar que la zona indefinida esté vacía, es decir, v>x Por ello, se propone como guarda

v x

Al finalizar el bucle se tendrá v=x+1:

1 n

azul blanco rojo

(17)

65 Invariante r ? u v x 1 n

3c) El invariante debe progresar hacia la postcondición

con cada iteración. Para ello, la zona indefinida debe decrecer. De hecho, el tamaño (número de bolas) de esta zona se puede tomar como función limitadora del bucle:

t=x-v+1

En efecto, I vx ->t>0.

El cuerpo de la iteración deberá consistir de unas instrucciones tales que, manteniendo el invariante, disminuyan la función limitadora:

opción:

color(v) = blanco: v:=v+1;

color(v) = azul: u:=u+1; perm(v,u); v:=v+1; color(v) = rojo: perm(v,x); x:=x-1

fopción

Veamos que la "opción" es correcta y mantiene el invariante:

• Siempre se cumple alguna de las guardas. Cabe recordar que el invariante afirma que cualquiera de las bolas es de uno de los tres colores que se citan, luego

66

color(v)=blancocolor(v)=azul color(v)=rojo

Invariante

r ?

u v x

1 n

• Para cada opción, cuando se parte de un estado en que

se cumple IB, la ejecución de la acción

correspondiente conduce de nuevo al invariante:

I vx color(v)=blanco: r ? u v x 1 n v+1 I vx color(v)=azul: r ? u v x 1 n v+1 intercambio u+1 I vx color(v)=rojo: r ? u v x 1 n v+1 x-1 intercambio

La eficiencia de los algoritmos

• Es inmediato comprobar que en cualquier caso de la "opción", la función limitadora decrece.

El algoritmo queda escrito como sigue: u:=0; v:=1; x:=n;

mientras vx hacer opción:

color(v) = blanco: v:=v+1;

color(v) = azul: u:=u+1; perm(v,u); v:=v+1; color(v) = rojo: perm(v,x); x:=x-1 fopción

fmientras

Talla = n (tamaño del vector)

Coste(n)=

1

(

)

1

n

n i

La eficiencia de los algoritmos

5.2.2 Búsqueda binaria. Enunciado del problema:

> Búsqueda de un elemento que tiene un valor dado X. > Inicialmente el vector se encuentra ordenado (ascendentemente)

> Supondremos, por simplicidad, que: - el vector es de enteros - la cota inferior del vector es 1 - la cota superior del vector es N

Definición del problema

algoritmo búsqueda_binaria

(datos v: Vector[b1 .. bn ] de TipoBase; x:TipoBase;

resultados está: lógico)

P = {x = X v = V ordenado(V) }

(18)

69

Estrategia:

como el vector está ordenado

ascendentemente, la búsqueda binaria se plantea como una búsqueda en el subvector donde se puede encontrar el elemento buscado, subvector de búsqueda.

En cada iteración de la búsqueda:

> Acceder al elemento central v[m] del subvector de búsqueda

> SI:

X = v[m] búsqueda finalizada

X < v[m] buscar en subvector izquierdo X > v[m] buscar en subvector derecho

v[1] v[2] ... v[m ]

v[N ] 1 2 izq m der N I {(i:1 i < izq: v[i] < X)#i:der $i N : X< v[i])

1izqN 1derN 1mN m=(izq+der)div2} t = der -izq + 1 ó número de elementos del

subvector de búsqueda

70

Diseño del algoritmo a partir del

invariante

¿El invariante se cumple al empezar la iteración?

En efecto, al inicio el subvector de búsqueda coincide con el vector v, por lo que

izq := 1; der:= N; m : = (izq + der) div 2

v[1] v[2] ... v[m ]

v[n]

izq 2 m der

Por tanto P inicioI

La eficiencia de los algoritmos

¿El invariante se cumple al terminar la iteración?

La postcondición

Q = {está = ( i: 1 i N: x = v[i]} se puede alcanzar de dos formas tras salir del bucle:

está = true v[m] = X

está = false i: 1 i N : X<> v[i]

Equivalentemente, se termina sii

v[m] = X izqder

Por tanto, seguiremos buscando si B = (v[m] <> X) #izq $der)

La eficiencia de los algoritmos

¿Se cumple el invariante tras cada iteración?

Las instrucciones que conforman el cuerpo de la iteración deben hacer que el invariante “progrese” hacia la postcondición con cada iteración. Con ello, el tamaño del subvector de búsqueda debe decrecer.

I (v[m] <> X) #izq $der) t = der -izq + 1 Cuerpo_iteración

I

Por tanto, en la primer iteración

v[1] v[2] ... v[m ]

<>x

v[n]

izq 2 m der

Si v[m] $x, el elemento estará en [m+1 .. der]

v[1] v[2] ... v[m ]

<>x

v[n]

1 2 m izq der

(19)

73 v[1] v[2] ... v[m ] <>x v[n] izq 2 der m N 74

Por tanto, el cuerpo de la iteración sería

opción

v[m] $x: izq:= m + 1 v[m] x: der:= m - 1 fopción

m := (izq + der) div 2

Veamos que la "opción" es correcta y mantiene el invariante y hace decrecer la función limitadora:

• Siempre se cumple alguna de las guardas:

si v[m] <> X entonces (v[m] $x) (v[m] x) • Para cada opción, cuando se parte de un estado en que

se cumple IB, la ejecución de la instrucción

correspondiente conduce de nuevo al invariante

Opción 1

I v[m] < X izq < der

izq:= m + 1

m := (izq + der) div 2

I

y la función limitadora decrece

La eficiencia de los algoritmos

Opción 2

I v[m] X izq < der

der:= m - 1

m := (izq + der) div 2

¿ I ?

y la función limitadora decrece

¡CUIDADO!

Supongamos que

- izq y der son consecutivos: izq = der -1. Por tanto,

m = izq

- izq =1. Por tanto m = 1

- v[m] X

v[1] v[2]

izq= m = 1

der

Al ejecutar la instrucción der :=m -1

¡der := 0! ¡No se cumple el invariante!

La eficiencia de los algoritmos

Este problema se soluciona re-escribiendo la opción

opción

v[m] $x: izq:= m + 1

v[m] x: der:= m

fopción

m := (izq + der) div 2

Ejercicios:

1.- Comprobar que con la modificación realizada, la

función limitadora decrece cuando v[m] x (pista: si está dentro del bucle izq der - 1)

2.- Comprobar que si izq y der son consecutivos, pero

v[m] $x no hay problemas.

Por tanto, la búsqueda binaria queda como sigue:

función búsqueda_binaria(v:Vector[1..N]de enteros;

x:entero) devuelve Lógico

var está:Lógico; m, izq, der :entero fvar

izq := 1; der := N;

(20)

77

m := (izq + der) div 2;

mientras (v[m] <> x) #izq $der) hacer opción

v[m] $x: izq:= m + 1 v[m] x: der:= m

fopción

m := (izq + der) div 2

fmientras devuelve está := (v[m] = x) ffuncion L / 02 B %<9 => C0D2 E = D? 67?

1 1

)

1

(

1

1

i 78 B 0 2% / C0D2 E >F(M >F(M >D@< ? M )?D?'

"

(

coste(n)

O(log

2

n), coste(n)

(1).

67?

n i

n

n

2 log 1 2 2

(log

)

log

1

Referencias

Documento similar

In medicinal products containing more than one manufactured item (e.g., contraceptive having different strengths and fixed dose combination as part of the same medicinal

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)

Package Item (Container) Type : Vial (100000073563) Quantity Operator: equal to (100000000049) Package Item (Container) Quantity : 1 Material : Glass type I (200000003204)

D) El equipamiento constitucional para la recepción de las Comisiones Reguladoras: a) La estructura de la administración nacional, b) La su- prema autoridad administrativa

b) El Tribunal Constitucional se encuadra dentro de una organiza- ción jurídico constitucional que asume la supremacía de los dere- chos fundamentales y que reconoce la separación

Cedulario se inicia a mediados del siglo XVIL, por sus propias cédulas puede advertirse que no estaba totalmente conquistada la Nueva Gali- cia, ya que a fines del siglo xvn y en