EjResueltos-recursividad

7

Click here to load reader

Transcript of EjResueltos-recursividad

Page 1: EjResueltos-recursividad

TEMA 5 Conceptos de Java para Estructuras de Datos Diseño recursivo y eficiente: soluciones Divide y Vencerás para la ordenación y la selección

EJERCICIOS RESUELTOS Ejercicio 1.- El método toString de una LEG es el siguiente: public String toString() { String res = ""; NodoLEG<E> aux; for (aux = primero; aux != null; aux = aux.siguiente) res += aux.dato.toString() + “\n”; return res; } Escribe la versión recursiva de este método, planteando el caso base y el caso general. Indica qué tipo de algoritmo recursivo es. Solución: * Caso base: lista vacía (devuelve la cadena vacía) * Caso general: lista con algún nodo (devuelve la descripción del primer nodo más la descripción del resto, que a su vez es otra lista) public String toString() { return toString(primero); } private String toString(NodoLEG <E> aux) { if (aux == null) return “”; // Caso base else return aux.dato.toString() + “\n” + // Caso general toString(aux.siguiente); } El algoritmo recursivo es lineal no final.

Page 2: EjResueltos-recursividad

Ejercicio 2.- Invertir recursivamente un array. Ejemplo:

Solución: public static <T> void invertir(T v[]) { invertir(v, 0, v.length - 1); } private static <T> void invertir(T v[], int inicio, int fin) { if (inicio < fin) { T tmp = v[inicio]; v[inicio] = v[fin]; v[fin] = tmp; invertir(v, inicio + 1, fin – 1); } } Ejercicio 3.- Función recursiva que devuelva el máximo de un array. Solución: public static <T extends Comparable<T>> T maximo(T v[]) { return maximo(v, 0); } private static <T extends Comparable<T>> T maximo(T v[], int inicio) { if (inicio == v.length) return null; else { T max = maximo(v, inicio + 1); if (max == null || v[inicio].compareTo(max) > 0) max = v[inicio]; return max; } }

A B C D D C B A

Page 3: EjResueltos-recursividad

Ejercicio 4.- Calcula la talla, las instancias significativas y la complejidad asintótica para cada una de ellas del siguiente método: public static <T extends Comparable<T>> void insercionDirecta(T a[]) { for (int i = 1; i < a.length; i++) { T elemAInsertar = a[i]; int posIns = i; for (; posIns > 0 && elemAInsertar.compareTo(a[posIns-1]) < 0; posIns--) { a[posIns] = a[posIns-1]; } a[posIns] = elemAInsertar; } } Solución: Talla:

N = a.length Instancias significativas:

Mejor caso: el vector de entrada está ordenado ascendentemente Peor caso: el vector de entrada está ordenado descendentemente

Ecuaciones de coste:

TinsercionDirectaM(N) = k1*N + k2

TinsercionDirectaP(N) = k3 + (k4*i + k5) = k4*N*(N+1)/2 + k5*N + k3

Complejidad asintótica:

TinsercionDirecta(N) (N) TinsercionDirecta(N) O(N2)

Ejercicio 5.- Analiza el coste de los siguientes métodos: a) Búsqueda dicotómica en un array ordenado: private static <E extends Comparable<E>> E buscar(E x, E v[], int inicio, int fin) { if (inicio > fin) return null; int mitad = (inicio + fin) / 2; int res = v[mitad].compareTo(x); if (res < 0) return buscar(x, v, mitad + 1, fin); if (res > 0) return buscar(x, v, inicio, mitad - 1); return v[mitad]; }

i=1N

Page 4: EjResueltos-recursividad

b) Búsqueda dicotómica en una lista ordenada: private static <E extends Comparable<E>> E buscar(E x, NodoLEG<E> n, int talla) { if (talla <= 0) return null; int mitad = talla / 2; NodoLEG<E> aux = n; for (int i = 0; i < mitad; i++) aux = aux.siguiente; int res = aux.dato.compareTo(x); if (res < 0) return buscar(x, aux.siguiente, talla – mitad - 1); if (res > 0) return buscar(x, n, mitad); return aux.dato; } Solución: a) Búsqueda dicotómica en un array ordenado:

Talla del problema: N = fin – inicio + 1 Sí que hay instancias significativas:

o Mejor caso: x está en la posición (inicio + fin)/2 o Peor caso: x no está en el array

Ecuaciones de recurrencia: o Mejor caso:

TbuscarM(N) = k

o Peor caso: Tbuscar

P(N=0) = k Tbuscar

P(N>0) = 1* TbuscarP(N/2) + k

Para la última ecuación aplicamos el teorema 3, con a=1 y c=2: Coste asintótico del método:

Tbuscar(N) (1) Tbuscar(N) (log2N)

b) Búsqueda dicotómica en una lista ordenada:

Talla del problema: N = talla Sí que hay instancias significativas:

o Mejor caso: x está en el nodo que ocupa la posición talla/2 o Peor caso: x no está en la lista

Ecuaciones de recurrencia: o Mejor caso:

TbuscarM(N) = k1*N + k2

o Peor caso: Tbuscar

P(N=0) = k Tbuscar

P(N>0) = 1* TbuscarP(N/2) + k1*N + k2

Para la última ecuación aplicamos el teorema 4, con a=1 y c=2: Coste asintótico del método:

Tbuscar(N) (N) Tbuscar(N) (N)

Page 5: EjResueltos-recursividad

Ejercicio 6.- Analiza el coste de los siguientes métodos: a) private static int sumar1(int v[], int ini, int fin) { int suma = 0; if ( ini == fin ) suma = v[ini]; if ( ini < fin ) { suma = v[ini] + v[fin]; suma += sumar1(v, ini+1, fin-1); } return suma; }

b) private static int sumar2(int v[], int ini, int fin) { int suma = 0; if ( ini == fin ) suma = v[ini]; if ( ini < fin ) { int mitad = (fin + ini) / 2; suma = sumar2(v,ini,mitad) + sumar2(v,mitad+1,fin); } return suma; }

Solución: a)

Talla del problema: x = fin – ini + 1 No hay instancias significativas pues hay que recorrer todo el vector en

cualquier caso Ecuaciones de recurrencia:

Tsumar1(x 1) = k Tsumar1(x > 1) = 1* Tsumar1(x – 2) + k

Para la última ecuación aplicamos el teorema 1, con a=1 y c=2: Coste asintótico del método:

Tsumar1(x) (x) b)

Talla del problema: x = fin – ini + 1 No hay instancias significativas pues hay que recorrer todo el vector en

cualquier caso Ecuaciones de recurrencia:

Tsumar2(x 1) = k Tsumar2(x > 1) = 2* Tsumar2(x / 2) + k

Para la última ecuación aplicamos el teorema 3, con a=2 y c=2: Coste asintótico del método:

Tsumar2(x) (x)

Page 6: EjResueltos-recursividad

Ejercicio 7.- Sea v un vector de componentes Integer positivas que se ajustan al perfil de una curva cóncava, es decir, que existe una única posición k en el vector tal que:

Los elementos a la izquierda de k están ordenados descendentemente Los elementos a la derecha de k están ordenados ascendentemente

Ejemplo:

Diseñar el método recursivo que más eficientemente determine dicha posición k. Indica las instancias significativas y analiza el coste del método.

Solución: public static int buscarPosK(Integer v[]) { return buscarPosK(v, 0, v.length - 1); } private static int buscarPosK(Integer v[], int inicio, int fin) { if (inicio > fin) return -1; else { int resAnt = 1, resSig = 1, mitad = (inicio + fin) / 2; if (mitad > inicio) resAnt = v[mitad-1].compareTo(v[mitad]); if (mitad < fin) resSig = v[mitad+1].compareTo(v[mitad]); if (resAnt < 0 && resSig > 0) return buscarPosK(v, inicio, mitad – 1); else if (resAnt > 0 && resSig < 0) return buscarPosK(v, mitad + 1, fin); else return mitad; } Talla del problema:

N = fin – inicio + 1 En la llamada más alta: N = v.length

Instancias significativas:

Mejor caso: la posición k se encuentra en la posición (inicio + fin) / 2. Peor caso: el vector v está totalmente ordenado. Por lo tanto, k coincide con uno

de los extremos del vector Ecuaciones de recurrencia:

Mejor caso: TbuscarPosK

M(N) = k Peor caso:

TbuscarPosKP(N=0) = k

TbuscarPosKP(N>0) = 1 * TbuscarPosK

P(N/2) + k Coste:

TbuscarPosK(N) (1) TbuscarPosK(N) O(log2N), aplicando el teorema 3 con a=1 y c=2.

4 3 2 1 2 3 4 5 6 7

k

Page 7: EjResueltos-recursividad

Ejercicio 8.- Una estrategia alternativa a la presentada para diseñar la ordenación por fusión (mergeSort) es la de dividir el array en tres partes, ordenarlas y después fusionarlas. Analícese su coste temporal e indíquese si mejora el del método mergeSort. Solución: Talla del problema:

N = fin – inicio + 1 En la llamada más alta: N = v.length

Instancias significativas:

No hay instancias significativas Ecuaciones de recurrencia:

TmergeSort_3(N≤1) =k1 TmergeSort_3(N>1) = 3 * TmergeSort_3(N/3) + TmezclaNaturalDyV_3(N) +k2

Coste asintótico:

TmergeSort_3(N) (N*log3N) ¿Es más eficiente? No, ya que N*log3N = N * log2N / log23, y log23 es una constante.