Recursividad + Pilas Java

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 9

RECURSIVIDAD  DIRECTA

Cuando la función recursiva se llama así misma de forma directa.


 INDIRECTA
Cuando una función inicial llama a una segunda función y ésta a su vez llama a la
anterior.

EJEMPLOS DE PROGRAMAS RECURSIVOS


Matrushka
1. Programa recursivo que calcula el Factorial de un número.
La recursión es una técnica consistente en definir una función que dentro de su
estructura se invoca o llama a sí misma. Puesto que en algunos lenguajes una función Sol.
puede llamar a otras funciones, se permite que una función también pueda llamarse a public class Factrec {
sí misma. public static void main(String[] args) {
int n, resultado;
Toda función definida recursivamente debe contener al menos una definición explícita
Scanner lee= new Scanner(System.in);
para alguno de sus argumentos. De no ser así la función puede caer en un bucle
System.out.print("Introduce un número entero");
infinito.
n= lee.nextInt();
DEFINICIÓN. resultado=frec(n); //Llamada al método recursivo
Se llama recursividad al proceso mediante el cual una función se llama a sí misma de System.out.println(resultado);
forma repetida, hasta que se satisface alguna determinada condición. El proceso se }
utiliza para procesos repetidos en las que cada acción se determina mediante un
resultado anterior. Se pueden escribir de esta forma muchos problemas iterativos. public static int frec(int num){ //Método recursivo
int res;
Ejemplo. Método o función que calcula el factorial de un número 5 frec(num)
if(num==1){ //Caso base
5! = 5*4! = 5*4*3! = 5*4*3*2! = 5*4*3*2*1! = 5*4*3*2*1*0! return 1; int res
}
Si asignamos 1 al factorial de 0 tendremos cómo resultado final que
else { res=num*frec(num-1); //Llamada recurrente
num==1
5! = 5*4*3*2*1*1 que es el resultado buscado }
return res; Res = num*frec(num-1) return 1
COMPONENTES DE UNA FUNCIÓN RECURSIVA
Para que un problema sea posible resolverlo mediante la recursión, debe ser posible }
identificar y definir los siguientes elementos: }
return res
 EL CASO BASE, es el resultado más simple o básico que tiene el problema.
 EL CASO RECURSIVO, se irá ejecutando tal manera que la última o la que está más 2. Crea un programa recursivo que obtenga la cantidad de dígitos de un número N.
cerca al caso base, nos determinará que esa función recursiva ha terminado. import java.util.Scanner;
import java.util.*;
TIPOS DE RECURSIVIDAD.
1 / 1/1 1/2
public class Digitosrec { }
public static void main(String[] args) { return res;
int n; }
Scanner lee= new Scanner(System.in); }
System.out.print("Introduce un número entero");
n= lee.nextInt();
EJERCICIOS
System.out.println("El número "+n+" tiene "+digi(n)+" digitos"); //Llamada al método recursivo
} 1. Escribir un programa recursivo que reciba un número N y luego imprima y calcule
la sumatoria del número introducido.
static int digi(int num) { //Método recursivo Ej. N = 5
if(num <= 0) return 0; //Caso base 5+4+3+2+1 = 15
return 1 + digi(num/10); //Llamada recurrente
} 2. Escribir un programa recursivo que imprima la serie de Fibonacci
} 3. Escribir un programa recursivo que compruebe si un número es binario. Un
número binario está formado únicamente por ceros y unos.
3. Sumar los números naturales hasta N de forma recursiva. 4. Escribir un programa recursivo que obtenga el resultado de elevar un número a
import java.util.Scanner; otro.
import java.util.*;

public class Sumarec {


public static void main(String[] args) {
int n, resultado;
Scanner lee= new Scanner(System.in);
System.out.print("Introduce un número entero");
n= lee.nextInt();
resultado = sumarecursiva(n); //Llamada al método recursivo
System.out.println(resultado);
}

public static int sumarecursiva(int numero) { //Método recursivo


int res;
if(numero == 1){ //Caso base
return 1;}
else{
res = numero + sumarecursiva(numero-1); //Llamada recursiva

2 / 1/1 2/2
PRÁCTICA RECURSIVIDAD PILAS
1. Crea un método que imprima por pantalla un Rectángulo a partir de los valores de DEFINICIÓN.
la base y la altura Una pila es un tipo de estructura de datos en la que sólo se pueden
2. Crea un método que imprima por pantalla un Triángulo rectángulo a partir del valor de la insertar y eliminar nodos en uno de los extremos del mismo. Estas
altura del triángulo. operaciones se conocen como “push” y “pop” respectivamente.
3. Crea un método que compruebe si una palabra está ordenada alfabéticamente. Además, las escrituras de datos siempre son inserciones de nodos, y
4. Crea un método que obtenga el número binario de un número N pasado como parámetro las lecturas siempre eliminan el nodo leído.
binario.
Estas características implican un comportamiento
5. Crea un método que compruebe si un número está ordenado de forma decreciente y
LIFO (Last In First Out), el último en entrar es el
creciente.
primero en salir.
6. Crea un método que compruebe si un número es simétrico. Los números simétricos son
iguales a partir del dígito central pero comparando en dirección opuesta Ejemplo de este tipo de etructura es una pila de
7. Crea un programa donde se pida en el principal la tabla de multiplicar deseada, en un platos. Sólo es posible agregar platos en la parte
método recursivo generar la tabla de multiplicar. Se multiplicara hasta querer llegar al superior de la pila, y sólo pueden tomarse del
numero 12 como resultado. mismo extremo.
8. Crea un programa donde ingreses 10 nombres de ciudades, y en un método recursivo
muestra las ciudades al reves (es decir del ultimo al primero)
9. Crea un programa donde se pida el nombre de una persona en el principal y en un método
recursivo mostrarlo de forma inversa.
10. Recorrer un array de forma recursiva. En una pila es muy importante que nuestro programa nunca pierda el valor del puntero
11. Buscar un elemento de un array de forma recursiva. al primer elemento.
12. Recorrer una matriz de forma recursiva. Teniendo en cuenta que las inserciones y borrados en una pila se hacen siempre en un
13. Calcular el valor de la posición fibonacci usando recursividad. extremo, lo que consideramos como el primer elemento de la Pila es en realidad el
14. Invertir un numero de forma recursiva. último elemento de la pila.
15. Calcula la potencia de un numero de forma recursiva, tanto para exponentes.
16. Suma los digitos de un numero de forma recursiva. OPERACIONES BÁSICAS CON PILAS
17. Haz una función que obtenga el maximo numero de un array, pasandole el array, el indice Las pilas tienen un conjunto de operaciones muy limitado, sólo permiten las
y el numero maximo actual. Otra función sin que sea necesario el tercer parámetro. Haz lo operaciones de “push” y “pop”:
mismo con el mínimo.  Push (Insertar): Agregar un elemento al final de la pila.
 Pop (Eliminar): Leer y eliminar un elemento del final de la pila.

INSERCIÓN DE ELEMENTOS EN LA PILA.


Las operaciones con pilas son muy simples, no hay casos especiales, salvo que la Pila
esté vacía.

3 / 1/1 3/2
a) INSERCIÓN EN UNA PILA VACIA 3. Guardamos el contenido del nodo para devolverlo como retorno, recuerda que la
Partiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero operación pop equivale a leer y borrar.
que apunte a él, además el puntero a la Pila valdrá NULO: 4. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.
El proceso es muy simple, bastará con que:
1. nodo.siguiente apunte a NULO.
2. Pila apunte a nodo.

Si la pila sólo tiene un nodo, el proceso sigue siendo válido, ya que el valor de
Pila.siguiente es NULO, y después de eliminar el último nodo la pila quedará vacía, y el
b) INSERCIÓN EN UNA PILA NO VACIA valor de Pila será NULO.
Podemos considerar el caso anterior como un caso particular de éste, la única EJEMPLO DE MANEJO DE PILAS EN JAVA
diferencia es que podemos y debemos trabajar con una pila vacía como con En el siguiente ejemplo se muestra el manejo de una pila que almacena un dato de
una pila normal. tipo entero.
De nuevo partiremos de un nodo a insertar, con un puntero que apunte a él, y
de una pila, en este caso no vacía: ********** CLASE Nodo.java **********
public class Nodo {
// Variable en la cual se va a guardar el valor.
private int valor;

// Variable para enlazar los nodos.


El proceso sigue siendo muy sencillo: private Nodo siguiente;
1. Hacemos que nodo.siguiente apunte a Pila.
/** Constructor en el que inicializamos el valor de las variables. */
2. Hacemos que Pila apunte a nodo. public void Nodo(){
this.valor = 0;
this.siguiente = null;
}

ELIMINACIÓN EN UNA PILA // Métodos get y set para los atributos.


Ahora sólo existe un caso posible, ya que sólo podemos leer desde un extremo de la public int getValor() {
pila (Tope). Partiremos de una pila con uno o más nodos, y usaremos un puntero return valor;
auxiliar, nodo: }
1. Hacemos que nodo apunte al primer elemento de la pila, es decir a Pila. public void setValor(int valor) {
2. Asignamos a Pila la dirección del segundo nodo de la pila: Pila.siguiente. this.valor = valor;
}
4 / 1/1 4/2
public Nodo getSiguiente() { Nodo nuevo = new Nodo();
return siguiente;
} // Agrega al valor al nodo.
nuevo.setValor(valor);
public void setSiguiente(Nodo siguiente) {
this.siguiente = siguiente; // Consulta si la pila esta vacia.
} if (esVacia()) {
} // Inicializa la pila con el nuevo valor.
inicio = nuevo;
********** CLASE Pila.java ********** }
public class Pila { // Caso contrario agrega el nuevo nodo al inicio de la pila.
// Puntero que indica el inicio de la pila o tambiEn conocida como el TOPE de la pila. else{
private Nodo inicio; nuevo.setSiguiente(inicio);
inicio = nuevo;
// Variable para registrar el tamaño de la pila. }
private int tamanio; // Incrementa el contador del tamaño.
tamanio++;
// Constructor por defecto. }
public void Pila(){
inicio = null; /** Elimina el elemento que se encuentra en el tope de la pila. */
tamanio = 0; public void retirar(){
} if (!esVacia()) {
/*Consulta si la pila es vacia. retorna true si el primer nodo (inicio) no apunta a otro */ // Asigna como primer nodo al siguiente de la pila.
public boolean esVacia(){ inicio = inicio.getSiguiente();
return inicio == null; // Decrementa el contador del tamaño de la pila
} tamanio--;
/** Consulta cuantos elementos (nodos) tiene la pila. retorna numero entero entre }
[0,n] donde n es el numero de elementos que contiene la Pila. */ }
/** Consulta el valor del nodo que se encuentra en la cima de la pila. retorna valor
public int getTamanio(){ del nodo. */
return tamanio;
} public int cima() throws Exception{
if(!esVacia()){
/** Agrega un nuevo nodo a la pila. parametro valor a agregar. */ return inicio.getValor();
public void apilar(int valor){ } else {
// Define un nuevo nodo. throw new Exception("La pila se encuentra vacia.");
5 / 1/1 5/2
} // Crea una pila auxiliar para guardar los valores que se vayan desapilando de la pila
} original.
Nodo pilaAux = null;
/** Busca un elemento en la pila. parametro referencia valor del nodo a buscar.
retorna TRUE si el valor de referencia existe en la pila. */ // Recoore la pila hasta llegar al nodo que tenga el valor igual que el de referencia.
while(referencia != inicio.getValor()){
public boolean buscar(int referencia){
// Crea una copia de la pila. // Crea un nodo temporal para agregarlos a la pila auxiliar.
Nodo aux = inicio; Nodo temp = new Nodo();

// Bandera para verificar si existe el elemento a buscar. // Ingresa el valor al nodo temporal.
boolean existe = false; temp.setValor(inicio.getValor());

// Recorre la pila hasta llegar encontrar el nodo o llegar al final de la pila. // Consulta si la pila auxiliar no a sido inicializada.
while(existe != true && aux != null){ if(pilaAux == null){

// Compara si el valor del nodo es igual que el de la referencia. // Inicializa la pila auxiliar.
if (referencia == aux.getValor()) { pilaAux = temp;
}
// Cambia el valor de la bandera.
existe = true; // Caso contrario si la pila auxiliar ya contiene elementos los agrega al inicio.
} else{
else{ temp.setSiguiente(pilaAux);
pilaAux = temp;
// Avanza al siguiente nodo. }
aux = aux.getSiguiente(); // Elimina el nodo del tope de la pila hasta llegar al nodo que se desea eliminar.
} retirar();
} }
// Retorna el valor de la bandera.
return existe; // Elimina el nodo que coincide con el de referencia.
} retirar();

/** Elimina un nodo de la pila ubicado por su valor. parametro referencia valor de // Regresa los valores de la pila auxiliar a la pila original mientras la pila auxiliar tenga
referencia para ubicar el nodo. */ elementos.
while(pilaAux != null){
public void remover(int referencia){
// Consulta si el valor existe en la pila. // Utiliza el metodo apilar para regresar los elementos a la pila original.
if (buscar(referencia)) { apilar(pilaAux.getValor());

6 / 1/1 6/2
// Avansa al siguiente nodo de la pila auxiliar. }
pilaAux = pilaAux.getSiguiente();
} // Elimina el nodo del tope de la pila hasta llegar al nodo que se desea eliminar.
retirar();
// Libera la memoria utilizada por la pila auxiliar. }
pilaAux = null;
} // Actualiza el valor del nodo.
} inicio.setValor(valor);

/** Actualiza el valor de un nodo en la pila. parametro referencia valor del nodo para //Regresa los valores de la pila auxiliar a la pila original mientras la pila auxiliar tenga
ubicar el que se desea actualizar. parametro valor por el cual se desea remplazar el elementos.
valor del nodo. */ while(pilaAux != null){
public void editar(int referencia, int valor){ // Utiliza el metodo apilar para regresar los elementos a la pila original.
// Consulta si el nodo existe en la pila apilar(pilaAux.getValor());
if (buscar(referencia)) {
// Avansa al siguiente nodo de la pila auxiliar.
// Crea una pila auxiliar. pilaAux = pilaAux.getSiguiente();
Nodo pilaAux = null; }
// Recoore la pila hasta llegar al nodo que tenga el valor igual que el de referencia. // Libera la memoria utilizada por la pila auxiliar.
while(referencia != inicio.getValor()){ pilaAux = null;
// Crea un nodo temporal para agregarlos a la pila auxiliar. }
Nodo temp = new Nodo(); }

// Ingresa el valor al nodo temporal. /** Elimina la pila */


temp.setValor(inicio.getValor()); public void eliminar(){
// Elimina el valor y la referencia a los demas nodos.
// Consulta si la pila auxiliar no a sido inicializada. inicio = null;
if(pilaAux == null){
// Reinicia el contador a 0.
// Inicializa la pila auxiliar. tamanio = 0;
pilaAux = temp; }
}
/** Despliega en pantalla los elementos de la pìla. */
// Caso contrario si la pila auxiliar ya contiene elementos los agrega al inicio. public void listar(){
else{ // Crea una copia de la pila.
temp.setSiguiente(pilaAux); Nodo aux = inicio;
pilaAux = temp;

7 / 1/1 7/2
// Recorre la pila hasta el ultimo nodo. case 1:
while(aux != null){ System.out.println("Dato a introducir: ");
System.out.println("|\t" + aux.getValor() + "\t|"); dato=lee.nextInt();
System.out.println("-----------------"); pila.apilar(dato);
aux = aux.getSiguiente(); break;
} case 2:
} pila.retirar();
} break;
case 3:
********** CLASE Main.java ********** int busca, inserta;
import java.util.Scanner; System.out.println("Dato a buscar---> ");
public class Main { busca=lee.nextInt();
public static void main(String[] args) { System.out.println("Dato a insertar---> ");
Pila pila = new Pila(); inserta=lee.nextInt();
int dato; pila.editar(busca, inserta);
Scanner lee = new Scanner(System.in); break;
System.out.println("<<-- Ejemplo de Pila -->>\n\n"); case 4:
int op=0; System.out.println("Dato a eliminar ---> ");
busca=lee.nextInt();
do { pila.remover(busca);
System.out.println("Tamaño de la PILA----> "+pila.getTamanio()); break;
System.out.println("<<-- MENU DE OPCIONES -->>\n\n"); case 5:
System.out.println("Dato a buscar---> ");
System.out.println("1. Insertar dato en la PILA.\n"
busca=lee.nextInt();
+ " 2. Eliminar de la PILA (Tope).\n"
System.out.println(pila.buscar(busca));
+ " 3. Modificar el valor de un NODO\n"
break;
+ " 4. Eliminar NODO con un valor específico\n"
case 6:
+ " 5. Buscar un valor en la PILA\n"
pila.eliminar();
+ " 6. Eliminar la PILA.\n"
break;
+ " 7. Verificar PILA vacia\n"
case 7:
+ " 8. Mostrar PILA\n"
System.out.println(pila.esVacia());
+ " 0. Salir\n");
break;
System.out.print("Número de opción---> ");
case 8:
op=lee.nextInt();
System.out.println("<<<<<< IMPRIMIENDO PILA >>>>>>");
switch (op) { System.out.println("Tamaño: "+pila.getTamanio());
pila.listar();
8 / 1/1 8/2
break; 6. Escriba una rutina que reciba una Pila P de números enteros y mueva sus elementos
} a una nueva Pila, pero invirtiendo el orden de salida de los mismos. Al finalizar la
}while (op!=0); Pila P no debe contener elementos.
} 7. Escriba una rutina que reciba dos Pilas P1 y P2 de números flotantes y apile las
} mismas en una nueva Pila resultante. Es de destacar que las Pilas recibidas no
deben sufrir ningún tipo de cambio o alteración.
APLICACIONES DE LAS PILAS 8. Escriba una rutina que reciba dos Pilas P1 y P2 de números enteros y proceda a
Con la implementación de las pilas es posible el uso de la modularización intercambiar sus elementos, pero manteniendo el orden de salida de los
(recursividad). La variable que llama al mismo procedimiento en el que está, habrá elementos. Al finalizar la rutina, la Pila P1 tendrá los elementos de la Pila P2 y esta
que guardarla así como el resto de variables de la nueva llamada, para a la vuelta a su vez tendrá los elementos de la Pila P1.
de la recursividad ir sacándolas, esto es posible a la implementación de pilas. 9. Escriba una rutina que reciba una Pila P de números enteros y devuelva una copia
Las pilas también se utilizan en muchas aplicaciones que utilizamos con frecuencia. Por exacta de la misma. Es de destacar que la Pila P no debe sufrir ningún tipo de cambio
ejemplo, la gestión de ventanas en Windows (cuando cerramos una ventana siempre o alteración.
recuperamos la que teníamos detrás). Otro ejemplo es la evaluación general de 10.Escriba una rutina que reciba una Pila P de números flotantes y devuelva una nueva
cualquier expresión matemática para evitar tener que calcular el número de variables Pila pero con los elementos invertidos, es decir el último de la Pila P, pasará a ser el
temporales que hacen falta. primero de la nueva Pila Es de destacar que la Pila P no debe sufrir ningún tipo de
cambio o alteración.
Por ejemplo:
11.Escriba una rutina que reciba una Pila P de números flotantes y devuelva otra pila,
3 + 4 * (8 – 2 * 5)
manteniendo el orden de salida de los elementos. Es de destacar que la Pila P no
debe sufrir ningún tipo de cambio o alteración.
12.En un archivo f están almacenados números enteros arbitrariamente grandes. La
disposición es tal que hay un número entero por cada línea de F. Escribir un
EJERCICIOS PILAS programa que muestre por pantalla la suma de todos los números enteros. Al
resolver el problema habrá que tener en cuenta que, al ser enteros grandes, no
1. Escriba un programa que reciba una Pila P de números enteros y mueva sus pueden almacenarse en variables numéricas.
elementos a una nueva Pila, pero manteniendo el orden de salida de los mismos.
Al finalizar la Pila P no debe contener elementos. 13.Utilizar dos pilas para guardar los dos primeros números enteros, almacenándose
digito a dígito. Al extraer los elementos de la pila, salen en orden inverso y, por lo
2. Realizar un programa que cuente la cantidad de elementos de una pila. La tanto, de menor peso a mayor peso; se suman digito con digito y el resultado se
estructura debe quedar en el estado original. guarda en una cola, también digito a digito. A partir de este primer paso se obtienen
3. Realizar un procedimiento que invierta el orden de una pila. el siguiente número del archivo, se guarda en una pila y, a continuación, se suma
digito a dígito con el número que se encuentra en la cola; el resultado se guarda en
4. Realizar un procedimiento que saque el elemento N de una pila. Tener en otra cola. El proceso se repite, nuevo número del archivo se mete en la pila, que se
cuenta que los demás elementos deben quedar en el mismo orden. suma con el número actual de la cola.
5. Realizar un procedimiento que ingrese un elemento en la posición N de una pila.
Tener en cuenta que los demás elementos deben quedar en el mismo orden.
9 / 1/1 9/2

También podría gustarte