Estructura de Datos de Pila en Java
Desliza para mostrar el menú
Una Stack es una estructura de datos que sigue el principio de Último en Entrar, Primero en Salir (LIFO). El mismo principio se aplica a una Deque, que ya se ha estudiado anteriormente, y los desarrolladores de Java recomiendan utilizar una Deque cuando una estructura de datos necesita operar bajo el principio LIFO. La estructura de datos Stack es obsoleta y no se recomienda en el desarrollo moderno de Java.
Sin embargo, algunas colecciones ya no se recomiendan y han sido obsoletas.
Obsoleto
Cuando un elemento está marcado como obsoleto, significa que los autores de la biblioteca o del lenguaje de programación aconsejan evitar su uso en código nuevo y recomiendan adoptar nuevos métodos, clases o enfoques que puedan proporcionar soluciones más seguras, eficientes o funcionales.
Un ejemplo es la clase Vector en Java. Sus métodos han sido desaprobados en favor de colecciones más modernas como ArrayList y LinkedList. Si un programador aún utiliza los métodos de Vector, el compilador puede emitir una advertencia indicando que estos métodos están desaprobados.
Ejemplo en Java:
Main.java
12345678910111213141516package com.example; import java.util.Vector; public class Main { public static void main(String[] args) { Vector<String> vector = new Vector<>(); // Adding an element (this method is deprecated) vector.addElement("Item"); // Compiler warning about the deprecated method // Note: 'addElement(java.lang.Object)' is deprecated. System.out.println(vector.get(0)); } }
Por lo tanto, no se recomienda utilizar una estructura de datos como Stack, pero la abordaremos en este capítulo porque es una estructura de datos interesante utilizada, por ejemplo, en la memoria Stack de Java.
Pila
Directo al grano, revisemos los métodos de la clase Stack:
Métodos
push(E element): agrega un elemento en la parte superior de la pila.
Main.java
123456789101112package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); } }
La adición se realiza de la misma manera que en ArrayList, así que veamos de inmediato este método en combinación con el método pop():
pop(): elimina y devuelve el elemento de la cima de la pila.
Main.java
1234567891011121314package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); stack.pop(); System.out.println("Stack after the `pop()` method: " + stack); } }
Este método elimina un elemento de la cima de la pila. Observa que el método pop() elimina el último elemento añadido a la pila. Así es exactamente como funciona el principio LIFO.
También puedes ver qué elemento está en la cima de la pila:
peek(): devuelve el elemento de la cima de la pila sin eliminarlo.
Main.java
123456789101112131415package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); String top = stack.peek(); System.out.println("Top element of the stack: " + top); System.out.println("Stack after the `peek()` method: " + stack); } }
Con este método, se observa el elemento superior en la pila.
Uso
Consideremos un ejemplo del uso de la estructura de datos Stack para la navegación entre páginas en un navegador (esas flechas de adelante y atrás que se utilizan frecuentemente).
Planificación de la implementación del historial del navegador e implementación de métodos para dos botones (goBack() y goForward()).
Si no está seguro a qué botones se hace referencia, se trata de estos botones de navegación:
Implementación de una clase con métodos para operar estos dos botones utilizando la estructura de datos Stack.
Funcionamiento
Se utilizarán dos pilas y una variable String. La primera pila almacenará los enlaces a los que se navega al hacer clic en la flecha de "atrás". La segunda pila almacenará los enlaces a los que se navega al hacer clic en la flecha de "adelante". También habrá una variable String que almacena el enlace de la página actual.
En esta clase, habrá cuatro métodos: visitPage(), goBack(), goForward() y getCurrentPage(). Se explicarán paso a paso.
El método visitPage() redirige a la URL especificada en el parámetro. Al moverse a una nueva página, el enlace anterior se añade a backStack. La forwardStack se vacía al navegar a una nueva página.
A continuación, se muestra la implementación en el código:
BrowserHistory.java
1234567891011121314151617181920212223242526import java.util.Stack; public class BrowserHistory { private Stack<String> backStack; private Stack<String> forwardStack; private String currentUrl; public BrowserHistory() { backStack = new Stack<>(); forwardStack = new Stack<>(); currentUrl = "https://codefinity.com/profile/my-home"; } public void visitPage(String url) { // When visiting a new page, add the current page to the "back" stack backStack.push(currentUrl); // Reset the "forward" stack as we moved to a new page forwardStack.clear(); // Set the current page to the new URL currentUrl = url; System.out.println("Visited page: " + url); } }
De este modo, es posible volver a la página anterior al navegar a una nueva página.
Implementación del método para retroceder. Su funcionamiento es el siguiente: se añade el enlace actual a la forwardStack, luego se elimina este enlace de la backStack y se asigna a currentUrl.
A continuación, se muestra la implementación en el código:
BrowserHistory.java
12345678910public void goBack() { if (!backStack.isEmpty()) { // Navigate to the previous page, move from the backStack to the forwardStack forwardStack.push(currentUrl); currentUrl = backStack.pop(); System.out.println("Went back to: " + currentUrl); } else { System.out.println("Cannot go back. Already at the beginning."); } }
Recuerda que el método pop() elimina el elemento de la parte superior de la pila y lo devuelve. Por lo tanto, al utilizar este método, asignamos de inmediato el valor de la URL a la variable currentUrl.
También verificamos que la pila backStack no esté vacía; de lo contrario, no será posible regresar al enlace anterior (simplemente porque no existirá). Si la pila está vacía, se muestra un mensaje correspondiente.
De manera similar, se implementa el método para navegar a la página siguiente. Simplemente se intercambian los elementos en la pila:
BrowserHistory.java
12345678910public void goForward() { if (!forwardStack.isEmpty()) { // Navigate to the next page, move from the forwardStack to the backStack backStack.push(currentUrl); currentUrl = forwardStack.pop(); System.out.println("Went forward to: " + currentUrl); } else { System.out.println("Cannot go forward. Already at the latest page."); } }
Ahora, solo queda implementar el método getCurrentPage(), que simplemente devolverá el valor de currentUrl.
Pruebas
A continuación, probemos todo esto en el método main. Utilizaremos el método visitPage() tres veces para asegurarnos de que estos enlaces se guarden en el historial. Luego, usaremos el método goBack() dos veces, seguido del método goForward() una vez, para verificar la funcionalidad de los métodos implementados.
Durante este proceso, seguiremos nuestro estado utilizando el método getCurrentPage(). Puedes ejecutar el siguiente código y también probar insertando más enlaces y utilizando diferentes métodos para comprobar la funcionalidad de esta clase:
Main.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778package com.example; import java.util.Stack; class Main { public static void main(String[] args) { BrowserHistory browser = new BrowserHistory(); System.out.println("Default page: " + browser.getCurrentPage()); browser.visitPage("https://codefinity.com/courses/tracks/7dfbcd35-5cde-49d3-80f1-bf1096487903"); browser.visitPage("https://codefinity.com/courses/v2/8204075c-f832-4cb9-88b1-4e24e74ebdcb/bb00e195-715e-477d-8927-964e6e27cf16/e66c57b4-5f36-43b2-bd3b-e1398044fcab"); browser.visitPage("https://codefinity.com/courses/v2/8204075c-f832-4cb9-88b1-4e24e74ebdcb/bb00e195-715e-477d-8927-964e6e27cf16/1585fb29-47cd-47a6-9fb3-5b391cad24e0"); System.out.println("Current Page after visiting 3 pages: " + browser.getCurrentPage()); browser.goBack(); browser.goBack(); System.out.println("Current Page after going back 2 times: " + browser.getCurrentPage()); browser.goForward(); System.out.println("Current Page after going forward: " + browser.getCurrentPage()); } } class BrowserHistory { private Stack<String> backStack; private Stack<String> forwardStack; private String currentUrl; public BrowserHistory() { backStack = new Stack<>(); forwardStack = new Stack<>(); currentUrl = "https://codefinity.com/profile/my-home"; } public void visitPage(String url) { // When visiting a new page, add the current page to the "back" stack backStack.push(currentUrl); // Reset the "forward" stack as we moved to a new page forwardStack.clear(); // Set the current page to the new URL currentUrl = url; System.out.println("Visited page: " + url); } public void goBack() { if (!backStack.isEmpty()) { // Navigate to the previous page, move from the backStack to the forwardStack forwardStack.push(currentUrl); currentUrl = backStack.pop(); System.out.println("Went back to: " + currentUrl); } else { System.out.println("Cannot go back. Already at the beginning."); } } public void goForward() { if (!forwardStack.isEmpty()) { // Navigate to the next page, move from the forwardStack to the backStack backStack.push(currentUrl); currentUrl = forwardStack.pop(); System.out.println("Went forward to: " + currentUrl); } else { System.out.println("Cannot go forward. Already at the latest page."); } } public String getCurrentPage() { return currentUrl; } }
Recuerda que la clase Stack es obsoleta y no se recomienda su uso en el desarrollo moderno de Java. En su lugar, es preferible utilizar Deque, que es una alternativa más eficiente. En este ejemplo, Stack se implementa basándose en el principio LIFO, y también puedes implementar Deque, ya que es una cola de doble extremo que admite tanto los principios FIFO como LIFO.
1. ¿Cuál es el principio fundamental de una estructura de datos Stack?
2. ¿Cuál es el método utilizado para agregar un elemento en la parte superior de la pila en Java?
3. ¿Cuál de las siguientes colecciones de Java se considera una alternativa más moderna a Stack?
4. En Java, ¿qué devolverá el método pop() de una Stack?
¡Gracias por tus comentarios!
Pregunte a AI
Pregunte a AI
Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla