Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


ESTRUCTURAS Y BASES DE DATOS, Apuntes de Desarrollo de Sistemas de Telecomunicación e Informáticos

Asignatura: ESTRUCTURA DE DATOS, Profesor: UEMC UEMC, Carrera: Ingeniero Técnico de Telecomunicación, especialidad en Sistemas Electrónicos, Universidad: UVA

Tipo: Apuntes

2013/2014

Subido el 14/06/2014

240300
240300 🇪🇸

1 documento

1 / 30

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
TEMA 2 — ANÁLISIS DE ALGORITMOS
1. ANÁLISIS DE EFICIENCIA DE ALGORITMOS: notación asintótica
2. TÉCNICAS DE DISEÑO DE ALGORITMOS
2.1. Recursividad
2.2.
Divide y vencerás
2.3.
Fuerza bruta 2.4.
Backtracking
2.5. Programación dinámica
2.6. Algoritmos voraces
ANÁLISIS DE EFICIENCIA DE ALGORITMOS
Un algoritmo es una secuencia nita de instrucciones precisas y no ambiguas,
que colaboran todas ellas juntas para realizar una tarea que resuelva un
problema.
Un algoritmo debe ser nito.
1. Criterios de eciencia
A la hora de evaluar un algoritmo, seguiremos unos criterios de eciencia.
A la hora de elegir entre varios algoritmos, utilizaremos 2 criterios básicos,
veces contradictorios entre ellos:
Fácil de entender, codicar y depurar : suelen resolver tareas
sencillas
Uso eciente de los recursos: uso de memoria y tiempo de cómputo
(se desea que sea rápido)
Si complicamos las instrucciones, dejarán de ser fáciles usarán más
recursos más lento
La importancia de los criterios depende de:
Nº de ejecuciones
Tamaño de la entrada
2. Medida del tiempo de ejecución de un programa
Este tiempo dependerá de:
Tamaño de la entrada nº de datos
En ocasiones suele decirse “Magnitud de la entrada”
Naturaleza y velocidad de las instrucciones máquina
Calidad del código que genere el compilador
Cada paso es independiente del sgte
La forma de resolverlo se va a basar en seguir
una serie de decisiones
Cada paso influye en
el sgte
Lo que más inuye
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e

Vista previa parcial del texto

¡Descarga ESTRUCTURAS Y BASES DE DATOS y más Apuntes en PDF de Desarrollo de Sistemas de Telecomunicación e Informáticos solo en Docsity!

TEMA 2 — ANÁLISIS DE ALGORITMOS

  1. ANÁLISIS DE EFICIENCIA DE ALGORITMOS: notación asintótica
  2. TÉCNICAS DE DISEÑO DE ALGORITMOS 2.1. Recursividad 2.2. Divide y vencerás 2.3. Fuerza bruta 2.4. Backtracking 2.5. Programación dinámica 2.6. Algoritmos voraces

ANÁLISIS DE EFICIENCIA DE ALGORITMOS

Un algoritmo es una secuencia finita de instrucciones precisas y no ambiguas, que colaboran todas ellas juntas para realizar una tarea que resuelva un problema.

Un algoritmo debe ser finito.

  1. Criterios de eficiencia

A la hora de evaluar un algoritmo, seguiremos unos criterios de eficiencia. A la hora de elegir entre varios algoritmos, utilizaremos 2 criterios básicos, veces contradictorios entre ellos:

  • Fácil de entender, codificar y depurar : suelen resolver tareas sencillas
  • Uso eficiente de los recursos: uso de memoria y tiempo de cómputo (se desea que sea rápido) Si complicamos las instrucciones, dejarán de ser fáciles usarán más recursos más lento

La importancia de los criterios depende de:

  • Nº de ejecuciones
  • Tamaño de la entrada
  1. Medida del tiempo de ejecución de un programa

Este tiempo dependerá de:

Tamaño de la entrada nº de datos En ocasiones suele decirse “Magnitud de la entrada”

  • Naturaleza y velocidad de las instrucciones máquina
  • Calidad del código que genere el compilador

Cada paso es independiente del sgteLa forma de resolverlo se va a basar en seguir una serie de decisiones

Cada paso influye en el sgte

Lo que más influye

  • Complejidad temporal del algoritmo base
  1. Eficiencia de un algoritmo

Se expresa en función del tiempo que necesita para ejecutarse y del espacio que ocupa en memoria. En general, se realiza en función del tamaño de entrada (entendiéndose como entrada al nº de elementos de entrada).

En ocasiones se entiende por tamaño de entrada algo distinto, es decir, la magnitud de la entrada. Ejemplo: calcular si 37 es primo frente a 1654827. El tamaño de la entrada es el mismo, pero no la magnitud

  1. Medidas de eficiencia de un algoritmo

T(n) ≡ tiempo que tarda en ejecutarse un algoritmo para una entrada de tamaño “n” E(n) ≡ espacio de memoria que necesita un algoritmo para ejecutarse, considerando un tamaño de entrada “n”

Estas dos medidas siempre van a estar referidas al peor de los casos : el que proporciona el peor tiempo de ejecución.

Ejemplo: ordenar un vector de 10 elementos

  • Peor caso: todos desordenados
  • Mejor caso: que estén ya ordenados
  • Caso promedio: que haya algún elemento ya posicionado correctamente

Para un tamaño fijo de “n”

  • CASO PEOR: proporciona un peor tiempo de ejecución
  • CASO MEJOR: proporciona el mejor tiempo de ejecución
  • CASO PROMEDIO: se corresponde con aquél en el que hacemos la media entre todas las entradas posibles
  1. Análisis asintótico
  • Teórico Consiste en analizar una a una las instrucciones del algoritmo y de esta forma calcular el tiempo total
  • Experimental Consideramos el algoritmo como una caja negra a la que vamos proporcionando las entradas y medimos el tiempo de ejecución para cada una de ellas
  1. Análisis teórico de los algoritmos
  • (^) Acciones elementales
  • Operaciones aritméticas

EJEMPLO DE ANÁLISIS DE ALGORITMO

Algoritmo de ordenación de burbuja de un vector v=[1,…n] de enteros

v: vector[1,…n] de enteros Para i←1 hasta n-1, i+ Para j←n hasta i+1, j-

Si v[j-1] > v[j] entonces 1

temp←v[j] 1 v[j-1]←v[j] 1 v[j]←temp 1 fin_si fin_para fin_para

Si n→∞ ⇒ T(n) ≈ n 2

  1. Análisis teórico de los algoritmos

Notación matemática utilizada para representar los tiempos que tardan los algoritmos, esto es, el tiempo que tarda en ejecutase un algoritmo en función del tamaño de entrada.

Se definen tres tipos de notación:

  • Notación O (big-omicron)⇒caso peor
  • Notación Ω (omega) ⇒ caso mejor
  • Notación Θ (big-theta) ⇒ caso promedio
  • Acotación superior

4*(n-i)

f(n) nunca se va a comportar peor que g(n), porque g(n) es su cota superior. Cuando el tiempo de ejecución de un algoritmo es O(g(n)) se dice que tiene una velocidad de crecimiento, o un orden de complejidad temporal, de g(n). La acotación superior se usa para representar el peor de los casos.

  • Acotación inferior

Cota superior de f (n)

REGLA DE LA SUMA Los términos g(n) y h(n) han de ser positivos

EJEMPLO DE ANÁLISIS ASINTÓTICO

Comprobar que f(n)=3n^2 +2n-5 es del orden de O(n 2 )

Para ello debemos probar que: 3n 2 +2n-5 ≤cn 2

Despejando c, obtenemos que c=5 por lo que: 3n 2 +2n-5 ≤5n 2 Diremos entonces que: f(n) Є O(n 2 )

Comprobar si f(n)=(n+1) 2 Є O(n 2 )

Según la notación vista anteriormente, se debe probar que: (n+1) 2 ≤ cn^2

Otra forma de resolverlo es: f(n)=f1(n)+f2(n)+f3(n)= n 2 +2n+

f1(n) Є O(n 2 ) f2(n) Є O(2n) f3(n) Є O(1)

Toda función está acotada superiormente por ella misma

Comprobar si f(n)=3n^3 + 2n^2 Є O(n 3 )

Primera forma de resolverlo, según la definición: 3n 3 + 2n^2 ≤ cn^3

n=1 c≥ 5 n=2 c≥ 4

La otra forma de resolverlo: f(n)=f1(n)+f2(n)= 3n^3 + 2n 2

f1(n) Є O(3n 3 )

Regla de la suma: n^2 +2n+1 Є O(máx{n^2 ,2n,1}) n^2 +2n+1 Є O(n^2 ) ⇒ f(n) Є O(n 2 )

Regla de la suma: 3n^3 +2n 2 Є O(máx{3n^3 , 2n^2 }) 3n^3 +2n 2 Є O(n^3 ) ⇒ f(n) Є O

T peor (n) Є Ω(Tpromedio(n)) Es la que más se ajusta, por lo que es la que

daríamos

T peor (n) Є Ω(Tmejor(n))

T promedio(n) Є O (Tpeor (n))

T promedio(n) Є Ω(Tmejor (n))

T mejor(n) Є O (Tpromedio(n)) Es la que más se ajusta, por lo que es la que

daríamos

T mejor(n) Є O (Tpeor (n))

Ejemplo: supongamos un algoritmo tal que su T (^) promedio(n) Є Θ (f(n)) ¿ T (^) peor

(n) Є Ω(f(n))?

Tpromedio (n) Є O(f(n))

Tpromedio (n) Є Θ (f(n))

Tpromedio (n) Є Ω(f(n))

Sabemos que: T peor (n) Є Ω(Tpromedio (n))

T promedio(n) Є Ω(f(n))

TÉCNICAS DE DISEÑO DE ALGORITMOS

Vamos a ver las principales técnicas de diseño de algoritmos: ♥ Recursividad ♥ Divide y vencerás ♥ Fuerza bruta ♥ Backtracking o vuelta atrás ♥ Algoritmo voraces ♥ (^) Programación dinámica

1. RECURSIVIDAD

Definición

Un módulo es recursivo cuando dentro de su ejecución existen una o varias llamadas a sí mismo.

Por composición:

T peor(n) Є Ω(f(n))

Ejemplo: el factorial de un número n! =n*(n-1)!

Propiedades

a. Deben existir uno o varios caso base donde no se haga uso de la recursividad Es decir, deberá haber un caso en el que se pare la recursividad porque si no será un bucle infinito. El tamaño de la entrada E es cada vez menor hasta llegar al caso base (cada vez son problemas más sencillos)

Ejemplo: en el caso anterior, (n-1)! es más sencillo que n!

FUNCTION FACT (N:INTEGER):

INTEGER

BEGIN

IF n = 1 THEN FACT := 1 ELSE FACT := n ***** FACT(n-1) END;

Operación de comparación

Operación de asignación

Operación de asignación + producto

Para averiguar cuál es la complejidad del algoritmo, hacemos uso del análisis teórico, puesto que dispongo de las líneas de código:

Ecuaciones de recurrencia

Hay dos formas para resolver una ecuación de complejidad, dependiendo de la estructura que posea:

Ejemplo: en el caso del factorial c = 4

Nº de llamadas recursivas

Tiempo de las ops recursivas

Ops no recursivasa ≡ nº llamadas recursivas n-b ≡ tamaño de la entrada en la llamada recursiva c*nK^ ≡nº operaciones no recursivas

Prueba de corrección

Para demostrar que un algoritmo recursivo funciona: a. Tiene que existir un salida no recursiva en el algoritmo b. Cada llamada recursiva se refiere siempre a un problema más sencillo c. Supuesto que las llamadas recursivas funcionan, el algoritmo debe funcionar

Ejemplo: en el caso del factorial

  • Salida no recursiva con n=
  • La llamada recursiva se hace con (n-1), más sencillo que la llamada anterior
  • Si la llamada recursiva funciona y devuelve (n-1)!, entonces el algoritmo devuelve n!

Ejemplo: Secuencia de Fibonacci

La sucesión de Fibonacci es la sucesión infinita de nº naturales tales que 0 1 1 2 3 5 8 13

Versión recursiva del método:

Algoritmo fibonacci Entrada entero n

Operación comparación Salida entero n

Operación asignación Si n≤2 entonces Devolver n

Operación lógica + asignación Si_no Devolver fibonacci (n-1)+fibonacci (n-2)

Al igual que antes, calculamos la complejidad del algoritmo como:

Puesto que (n-1)>(n-2), lo que estoy dando es una cota superior a mi problema:

Según esta fórmula:

Fib(2) + Fib(1) = Fib (3)

Fib(0) + Fib(1) = Fib (2)

Fib(1)Fib(0)

Es irresoluble no es acotable, es infinito Para n=

Hemos calculado 8 veces los casos base Se dice que es un problema superpuesto (calculo muchas veces lo mismo, el mismo subproblema) esto provoca el orden exponencial. A medida que aumenta n, este problema aumenta de escala y por lo tanto, estamos calculando muchas veces los mismos subproblemas.

Los problemas que presentan estas características se llaman ALGORITMOS SE PROBLEMAS SUPERPUESTOS.

Versión iterativa del método:

Algoritmo fibonacci entrada entero n salida entero n local entero anterior, actual, x, i si n≤2 entonces Devolver n anterior:=0, actual:= para i=2 hasta n x:=anterior anterior:=actual actual:=actual+x fin_para devolver actual

Los problemas recursivos y superpuestos no pueden ir juntos, se repelen.

2. DIVIDE Y VENCERÁS

Resumen: un problema se divide en subproblemas. Estos subproblemas son más sencillos porque la entrada es menor. Este subproblema se dividirá a su vez en un subproblema trivial.

Definición

Orden exponencial Fib(5)Fib(4)Fib(3)Fib(3)Fib(2)Fib(2)Fib(1) Fib(1)Fib(0)Fib(1)Fib(0)Fib(1)Fib(2)Fib(1)Fib(0)Conseguimos reducir la complejidad. Ésta pasa a ser O(n) Lineal resoluble

IF (I>J) THEN

BÚSQUEDA : = FALSE

ELSE_IF V[I]=X THEN

BÚSQUEDA : = TRUE

ELSE

BÚSQUEDA : = BÚSQUEDA (V,I+ 1 ,J,X)

END;

La complejidad del algoritmo es:

Realmente no es un divide y vencerás porque el tamaño de entrada NO SE REDUCE NOTABLEMENTE, ya que sólo se reduce en 1 unidad. En un buen “Divide y vencerás”, cada subproblema debería ser de tamaño: n, n/2, n/4,… hasta llegar a una entrada de tamaño 1. En este ejemplo, esto supondría llegar a un vector de 1 elemento.

Ejemplo: Búsqueda de un elemento en un vector (II)

Una forma alternativa de buscar un elemento de un vector es:

FUNCTION BUSQUEDA (VAR V: TVECTOR; I,J,X: INTEGER): BOOLEAN VAR MED: INTEGER BEGIN IF I>J THEN BUSQUEDA := FALSE ELSE_IF J-I=

BUSQUEDA := TRUE ELSE BEGIN MED : = (I+J) DIV 2 BUSQUEDA := BUSQUEDA (V,I,MED,X) OR BUSQUEDA (V,MED+ 1 , J,X) END; END;

n

El tamaño de la entrada se ha decrementado en una unidad

XSegunda mitad del Є (I,J) vector

Primera mitad del vectorJIMED

n/2 n/

n/

Análisis de la complejidad:

A pesar de utilizar el divide y vencerás, no hemos conseguido nada porque sigue siendo lineal e incluso ha empeorado ligeramente (porque a=2).

Ejemplo: Búsqueda de un elemento en un vector (III)

Supongamos que el vector está ordenado ascendentemente. MED : = (I+J) DIV 2

FUNCTION BUSQUEDA (VAR V: TVECTOR; I,J,X: INTEGER): BOOLEAN VAR MED: INTEGER BEGIN MED : = (I+J) DIV 2 IF V[MED]=X THEN

BUSQUEDA := TRUE ELSE_IF V[MED] > X THEN

BUSQUEDA (V,I,MED- 1 ,X) ELSE BUSQUEDA (V,MED+ 1 ,J,X) END;

Análisis de la complejidad:

Ejemplo: Potencia entera (an^ )

a Є R+^ , n Є Z +

MEDIMEDMEDIMEDMEDJMED +1JI………Desecho la parte derecha del vector X Є (I,MED)

Desecho la parte izq del vectorSi se hace una búsqueda no se hace la otra, por eso X Є (MED,J) a=1 y no a=

Log(n) es mejor comportamiento que “n”

ELSE { N ES IMPAR }

POT := A * POT (A * A, N DIV 2)

END;

3. FUERZA BRUTA

Las características de ésta y las demás estrategias:

  • (^) Backtracking
  • Algoritmos Voraces
  • Programación Dinámica

Cumplen todas un esquema general:

  • Son problemas en los que tenemos que tomar n-decisiones, para llegar o construir la solución. En algunos casos como Backtracking o programación dinámica, cada una de estas decisiones influye sobre las otras (decisiones independientes). En otros casos, como Fuerza Bruta y Algoritmos voraces, estas decisiones son independientes. Al final, la solución se expresa en función de las soluciones que hemos tomado.
  • La verificación de estos problemas es relativamente sencillo, es decir, dada una secuencia de decisiones es fácil ver si ésta es la solución o no a mi problema.

Ejemplo: Problema de las N-Reinas

Se basa en que dispongo de un tablero de ajedrez de N*N de tal forma que se basa en hallar la disposición de las N Reinas de forma que ninguna de ellas esté en peligro (la reina avanza hacia adelante, atrás o en diagonales).

La estrategia de fuerza bruta explora todas las posibilidades.

Hay que tomar N decisiones: ¿Dónde coloco a cada una de las reinas? Árbol de decisiones:

  1. ¿Dónde coloco a la 1ª reina? Tengo N*N posibilidades

Hay un total de N*N tableros

  1. ¿Dónde coloco a la 2ª reina?