26.11.2014 Views

Ejercicios de Genéricos y Algoritmos

Ejercicios de Genéricos y Algoritmos

Ejercicios de Genéricos y Algoritmos

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Ejercicios</strong> <strong>de</strong> Genéricos y <strong>Algoritmos</strong><br />

1. Defina e implemente la clase Pila para enteros. Fíjese en la transparencia <strong>de</strong> clase. Haga<br />

una primera versión con un tamaño máximo fijo que se pasa al constructor (array) y sin<br />

comprobar errores. Luego compruebe errores y lance una excepción en caso <strong>de</strong> violación<br />

(sacar <strong>de</strong> una pila vacía o meter en una pila llena).<br />

2. Defina a partir <strong>de</strong> la Pila anterior una Pila sin restricciones <strong>de</strong> tamaño. Emplee una lista <strong>de</strong><br />

Elementos para que pueda crecer in<strong>de</strong>finidamente, con referencias al siguiente y al previo<br />

en la lista. Hágala <strong>de</strong> modo que si se suprimen elementos <strong>de</strong> la pila no se pierda la<br />

memoria, guár<strong>de</strong>la por si luego se aña<strong>de</strong>n más elementos no haya que pedir memoria.<br />

3. Defina a partir <strong>de</strong> la Pila anterior una Pila genérica, que pueda contener cualquier tipo <strong>de</strong><br />

Objeto, es <strong>de</strong>cir, que pueda emplearse luego como una pila <strong>de</strong> Strings o como una pila <strong>de</strong><br />

Coches.<br />

4. Defina a partir <strong>de</strong> la Pila anterior una Pila que valga para todos los Números (Numbers).<br />

5. Use la clase Pila genérica para invertir una palabra. A partir <strong>de</strong> este programa <strong>de</strong>terminar si<br />

una palabra es palíndromo (se lee igual <strong>de</strong> izquierda a <strong>de</strong>recha que <strong>de</strong> <strong>de</strong>recha a izquierda:<br />

reconocer, rotor, somos,..)<br />

6. Defina e implemente una función buscar que localice un elemento en un array <strong>de</strong><br />

elementos, ambos se le pasan como argumentos. Pruébela con enteros. Luego hágala<br />

genérica, para cualquier tipo <strong>de</strong> objetos. Suponga que los objetos tienen un método<br />

equals(obj o) que compara el objeto en curso (this) con el objeto que recibe como<br />

parámetro, este método <strong>de</strong>vuelve true si son iguales y false si no lo son.<br />

7. Defina e implemente una función or<strong>de</strong>nar que or<strong>de</strong>ne enteros <strong>de</strong> mayor a menor. Recibirá<br />

un array con los enteros a or<strong>de</strong>nar.<br />

8. Defina a partir <strong>de</strong> la función or<strong>de</strong>nar anterior una genérica que permita or<strong>de</strong>nar objetos.<br />

Recibirá un array con los objetos a or<strong>de</strong>nar. Suponga que los objetos tienen un método<br />

compareTo(obj o) que permite comparar el objeto en curso (this) con el objeto recibido,<br />

que <strong>de</strong>vuelve -1 si es menor que el recibido, 0 si son iguales y 1 si es mayor que el<br />

recibido. Use esta función con el array <strong>de</strong> enteros anterior. Apóyese en una función<br />

intercambiar que reciba un array <strong>de</strong> objetos y dos enteros, que marcan las posiciones <strong>de</strong> los<br />

elementos a intercambiar.<br />

9. Defina una clase Empleado, con nombre, apellidos, fecha <strong>de</strong> contratación y número <strong>de</strong><br />

empleado y use la función anterior para or<strong>de</strong>nar un array <strong>de</strong> Empleados. Use la antigüedad<br />

como criterio a seguir (es “mayor” si es más antiguo). Si entraron en el mismo día, utilice<br />

el número <strong>de</strong> empleado para <strong>de</strong>sempatar<br />

10. Defina una clase que representa una entrada <strong>de</strong> una agenda, con el nombre, primer apellido,<br />

segundo apellido, teléfono, e-mail y móvil. Use la función anterior para or<strong>de</strong>nar un array <strong>de</strong><br />

entradas <strong>de</strong> agenda, usando como criterio <strong>de</strong> or<strong>de</strong>nación los apellidos y luego el nombre.<br />

11. Defina e implemente un directorio <strong>de</strong> teléfonos. En el mismo tendrá entradas <strong>de</strong> agenda con<br />

los campos anteriores. Se buscará por el nombre y apellidos y <strong>de</strong>volverá la entrada <strong>de</strong><br />

agenda correspondiente. Estos esquemas, para no recorrer toda la información, que pue<strong>de</strong><br />

tener miles <strong>de</strong> entradas, se apoyan en tablas Hash, que tienen dos partes, una clave que nos<br />

permite buscar la información (nombre y apellidos) y una información a recuperar asociada<br />

a esa clave.<br />

Una posible implementación es mediante un array <strong>de</strong> listas <strong>de</strong> entradas <strong>de</strong> agenda. Para no<br />

recorrer todas las posiciones <strong>de</strong>l array se dispone <strong>de</strong> una función hash que nos <strong>de</strong>vuelve un


código que marca la posición <strong>de</strong>l array don<strong>de</strong> buscarlo. Por ejemplo, una función que sume<br />

el valor <strong>de</strong> todos los caracteres <strong>de</strong>l nombre y apellidos y obtenga el módulo respecto al<br />

tamaño <strong>de</strong>l array, esto nos <strong>de</strong>volverá un entero entre 0 y length-1. Suele no consi<strong>de</strong>rarse los<br />

blancos y pasarse las mayúsculas a minúsculas para que no <strong>de</strong>penda <strong>de</strong> cómo se escriba el<br />

nombre y los apellidos. En esa posición <strong>de</strong>l array estará una lista con todas entradas que<br />

tengan dicho código, se recorre y se busca, pero ya sobre una pequeña lista.<br />

Pruebe a insertar unas pocas entradas y luego a buscar alguna <strong>de</strong> ellas. Pruebe a insertar<br />

dos nombre iguales, que cambie simplemente en el or<strong>de</strong>n <strong>de</strong> los apellidos, para asegurar<br />

que irán a la misma posición.<br />

12. Use otra tabla Hash para contar palabras iguales. Deberá buscar cada palabra y si ya está<br />

incrementar el contador asociado. Si no está <strong>de</strong>berá insertarla con el contador a 1.<br />

13. Defina una función barajar que reor<strong>de</strong>na aleatoriamente los elementos <strong>de</strong> un array. Recibe<br />

un array y un objeto <strong>de</strong> tipo Random que genera números aleatorios. Recorre el array, en<br />

or<strong>de</strong>n <strong>de</strong>creciente, e intercambia la posición actual con una aleatoriamente elegida que va<br />

<strong>de</strong>s<strong>de</strong> la primera posición <strong>de</strong>l array a la actual. Pue<strong>de</strong> emplear la función intercambiar<br />

anterior. Para obtener una posición aleatoria llamar al método “int nextInt(int i)” que<br />

<strong>de</strong>vuelve un entero entre 0 y i-1.<br />

14. Construir un array <strong>de</strong> Strings que represente una baraja americana, con 4 palos (corazones,<br />

picas, diamantes y tréboles) y 12 cartas cada uno (as, 2, 3,…10, paje, reina, rey). Construir<br />

el array con dos bucles anidados. Construir una función repartir que dada una baraja<br />

<strong>de</strong>vuelva una mano <strong>de</strong> “n” cartas, empezando por el final <strong>de</strong>l array (¡la baraja está boca<br />

abajo!) y que suprime las cartas <strong>de</strong> la baraja (<strong>de</strong>l array), para evitar po<strong>de</strong>r dar dos veces la<br />

misma carta. Esta función recibe tres argumentos, un array <strong>de</strong> cartas, la baraja, otro array<br />

<strong>de</strong> cartas, la mano a construir, y un entero “n” con el número <strong>de</strong> cartas a dar a esa mano.<br />

Emplee esta función para repartir “n” cartas a “m” jugadores, recibiendo tanto n como m a<br />

través <strong>de</strong> los argumentos <strong>de</strong>l programa. Previamente <strong>de</strong>be barajar las cartas, para<br />

asegurarse que nadie sabe que carta se repartirán a cada uno.<br />

15. Construya una calculadora basada en la notación polaca inversa. Esta notación indica<br />

primero los argumentos y luego el operador a aplicar. Es <strong>de</strong>cir, 6+7 se ve como 6 7 +. Un<br />

ejemplo con una expresión más compleja sería: (6+2)*5-8/4 que sería 6 2 + 5 * 8 4 / -. En<br />

un primer paso <strong>de</strong>berá transforma la expresión a notación polaca inversa. El algoritmo, que<br />

se apoya en el uso <strong>de</strong> una pila, se muestra a continuación:<br />

• Mientras haya tokens a ser leídos:<br />

o Lea un token.<br />

o Si el token es un número, entonces agréguelo al final <strong>de</strong> la expresión <strong>de</strong><br />

salida<br />

o Si el token es un operador, o1, entonces<br />

mientras que haya un operador, o2, en el tope <strong>de</strong> la pila y o1 la<br />

prece<strong>de</strong>ncia <strong>de</strong> o1 es menor o igual que la <strong>de</strong> o2, retire <strong>de</strong> la pila o2,<br />

y póngalo al final <strong>de</strong> la expresión <strong>de</strong> salida<br />

ponga o1 en el tope <strong>de</strong> la pila<br />

o Si el token es un paréntesis abierto, entonces póngalo en la pila<br />

o Si el token es un paréntesis <strong>de</strong>recho<br />

Hasta que el token en el tope <strong>de</strong> la pila sea un paréntesis abierto,<br />

retire (pop) a los operadores <strong>de</strong> la pila y colóquelos al final <strong>de</strong> la<br />

expresión <strong>de</strong> salida.<br />

Retire y <strong>de</strong>scarte el paréntesis abierto <strong>de</strong> la pila<br />

Si la pila se termina sin encontrar un paréntesis abierto, entonces hay<br />

paréntesis sin pareja: Error, expresión errónea<br />

• Cuando no hay más tokens para leer:<br />

o Mientras todavía haya tokens <strong>de</strong> operadores en el stack


etire el operador <strong>de</strong> la pila y póngalo al final <strong>de</strong> la expresión <strong>de</strong><br />

salida<br />

Si encuentra un paréntesis en la pila, hay paréntesis sin la pareja<br />

correspondiente: Error, expresión errónea.<br />

La prece<strong>de</strong>ncia <strong>de</strong> los operadores es: ^ tiene mayor prece<strong>de</strong>ncia que los <strong>de</strong>más, *, /, y %<br />

tienen la misma entre si y tienen mayor prece<strong>de</strong>ncia (<strong>de</strong>ben evaluarse antes) que + y -, que<br />

tienen entre si la misma. A misma prece<strong>de</strong>ncia se opera <strong>de</strong> izquierda a <strong>de</strong>recha.<br />

Se recomienda apoyarse en dos funciones, esOperador, que <strong>de</strong>vuelve verda<strong>de</strong>ro si el<br />

argumento es un operador, y prece<strong>de</strong>ncia, que compara dos operadores y <strong>de</strong>vuelve cual<br />

tiene mayor prece<strong>de</strong>ncia.<br />

A modo <strong>de</strong> ejemplo se muestra la expresión 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3, que <strong>de</strong>be<br />

transformarse en 3 4 2 * 1 5 - 2 3 ^ ^ / +:<br />

Token Acción Salida<br />

3 agrega token a la salida 3<br />

Entrada: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3<br />

Stack <strong>de</strong><br />

operadores<br />

+ Push token al stack 3 +<br />

4 agrega token a la salida 3 4 +<br />

Notas<br />

* Push token al stack 3 4 * + * tiene mayor prece<strong>de</strong>ncia que +<br />

2 agrega token a la salida 3 4 2 * +<br />

/<br />

Pop stack a la salida 3 4 2 * + / y * tienen la misma prece<strong>de</strong>ncia<br />

Push token al stack 3 4 2 * / + / tiene mayor prece<strong>de</strong>ncia que +<br />

( Push token al stack 3 4 2 * ( / +<br />

1 agrega token a la salida 3 4 2 * 1 ( / +<br />

- Push token al stack 3 4 2 * 1 - ( / +<br />

5 agrega token a la salida 3 4 2 * 1 5 - ( / +<br />

)<br />

Pop stack a la salida 3 4 2 * 1 5 - ( / + Repite hasta que sea encontrado "("<br />

Pop stack 3 4 2 * 1 5 - / + Descarta paréntesis emparejados<br />

^ Push token al stack 3 4 2 * 1 5 - ^ / + ^ tiene mayor prece<strong>de</strong>ncia que /<br />

2 agrega token a la salida 3 4 2 * 1 5 - 2 ^ / +<br />

^ Push token al stack 3 4 2 * 1 5 - 2 ^ ^ / + ^ es evaluado <strong>de</strong> <strong>de</strong>recha a izquierda<br />

3 agrega token a la salida 3 4 2 * 1 5 - 2 3 ^ ^ / +<br />

end Pop todo el stack a la salida 3 4 2 * 1 5 - 2 3 ^ ^ / +<br />

16. En un segundo paso, implemente un evaluador <strong>de</strong> expresiones en notación polaca inversa.<br />

El algoritmo es relativamente simple, se basa en usar una pila:<br />

• Si hay elementos en la ban<strong>de</strong>ja <strong>de</strong> entrada:<br />

i. Leer el primer elemento <strong>de</strong> la ban<strong>de</strong>ja <strong>de</strong> entrada.<br />

ii. Si el elemento es un operando, poner el operando en la pila<br />

iii. Si no, el elemento es un operador, con dos argumentos<br />

1. Si hay menos <strong>de</strong> 2 argumentos en la pila: Error, expresión errónea<br />

2. Si no, tomar los últimos 2 operandos <strong>de</strong> la pila<br />

3. Evaluar el operador con respecto a los operandos<br />

4. Introducir el resultado (si lo hubiere) en la pila.<br />

• Si hay un sólo elemento en la pila, el valor <strong>de</strong> ese elemento es el resultado


• Si hay más <strong>de</strong> un elemento en la pila: Error, expresión errónea.<br />

A modo <strong>de</strong> ejemplo se muestra la expresión algebraica 5+((1+2)*4)-3, que se traduce a la<br />

notación polaca inversa como 5 1 2 + 4 * + 3 - y se evalúa <strong>de</strong> izquierda a <strong>de</strong>recha según se<br />

muestra en la siguiente tabla:<br />

Entrada Operación Pila Comentario<br />

5 Introducir en la pila 5<br />

1 Introducir en la pila 5, 1<br />

2 Introducir en la pila 5, 1, 2<br />

+ Suma 5, 3<br />

Tomar los dos últimos valores <strong>de</strong> la pila (1, 2) y<br />

sustituirlos por el resultado (3)<br />

4 Introducir en la pila 5, 3, 4<br />

* Multiplicación 5, 12<br />

+ Suma 17<br />

Tomar los dos últimos valores <strong>de</strong> la pila (3, 4) y<br />

sustituirlos por el resultado (12)<br />

Tomar los dos últimos valores <strong>de</strong> la pila (5, 12) y<br />

sustituirlos por el resultado (17)<br />

3 Introducir en la pila 17, 3<br />

− Resta 14<br />

Tomar los dos últimos valores <strong>de</strong> la pila (17, 3) y<br />

sustituirlos por el resultado (14)

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!