A stack is a linear data structure that follows the Last In, First Out (LIFO) principle which means that the last element added to the stack is the first one to be removed .
• In stack the insertion and deletion of elements happen only at one endpoint.
• It is named stack because it has the similar operations as the real-world stacks.

Stack as an ADT:
A stack is an Abstract Data Type (ADT), that is popularly used in most programming for tasks like function calls, expression, evaluation, and undo operations.
• It supports two main operation that is push and pop.
Case 1: Basically when we “push” an element onto the stack, it gets added to the top of the stack.
Case 2: Similarly when we “pop” an element ,the top most element gets removed, which means the last element entered is the first one to be removed, as it follows the principle of Last-In-First-Out(LIFO).
Key points to be Remembered:
- Most Importantly Insertion of an element into stack are called PUSH operation.
- And ,Deletions of an element from stack are called as POP operation.
- Plus, when the stack is full it is said to “STACK OVERFLOW“.
- And, when the stack becomes empty it is referred as “STACK UNDERFLOW“.
Stack Operations:
Stack operations are generally used to extract information and data from a stack data structure. They are also used in memory management and parsing algorithms.
Some operations which can be performed in Stack are mentioned below:
1.) Push: This operation adds an element to the top of the stack.

2.) Pop: This operation removes the top element from the stack.

3.) Empty: Tests if this stack is empty.

4.) Search: Searches for the specified object in the stack and returns its position relative to the top of the stack.

Here’s a simple example demonstrating the usage of stack:
import java.util.Stack;
public class Main {
public static void main(String[] args) {
// Create a stack
Stack<Integer> stack = new Stack<>();
// Push elements onto the stack
stack.push(1);
stack.push(2);
stack.push(3);
// Print the stack
System.out.println("Stack: " + stack);
// Pop an element from the stack
int poppedElement = stack.pop();
System.out.println("Popped element: " + poppedElement);
// Peek at the top element of the stack
int topElement = stack.peek();
System.out.println("Top element: " + topElement);
// Check if the stack is empty
System.out.println("Is stack empty? " + stack.isEmpty());
// Search for an element in the stack
int index = stack.search(2);
if (index != -1) {
System.out.println("Element 2 found at index " + index + " from the top of the stack.");
} else {
System.out.println("Element 2 not found in the stack.");
}
}
}
Output:
Stack: [1, 2, 3]
Popped element: 3
Top element: 2
Is stack empty? false
Element 2 found at index 1 from the top of the stack.
Advantages of Stack:

‣ Simple Implementation:
Stacks are relatively simple to implement and understand. They follow the Last In, First Out (LIFO) principle, making them intuitive for many applications.
‣ Efficient Memory Management:
Stacks use a fixed amount of memory, which makes memory management more predictable and efficient compared to dynamic data structures like linked lists or arrays.
‣ Support for Recursion:
Stacks are essential for implementing recursion in programming languages. They provide a mechanism for storing intermediate results and returning to previous function calls.
‣ Undo Mechanism:
Stacks are commonly used to implement an “undo” mechanism in applications. Operations are pushed onto the stack as they are performed, allowing users to reverse the actions by popping items off the stack.
‣ Function Call Stack:
In programming languages, stacks are used to manage function calls and local variables. Each function call creates a new stack frame, allowing for nested function calls and proper variable scoping.
Disadvantages of Stack:

‣ Limited Access:
Stacks have limited access compared to other data structures like arrays or linked lists. Elements can only be accessed from the top of the stack, making it difficult to access or modify items in the middle of the stack.
‣ Fixed Size:
Some stack implementations have a fixed size, which can lead to stack overflow errors if the stack exceeds its capacity. Dynamic resizing can mitigate this issue but adds complexity to the implementation.
‣ Not Suitable for All Problems:
Stacks are not suitable for all problems. For example, they are not efficient for searching or sorting large datasets. Other data structures like queues or trees may be more appropriate for certain scenarios.
‣ Memory Management Issues:
In low-level programming languages like C or C++, manual memory management of stacks can lead to memory leaks or stack overflow errors if not handled properly.
‣ Limited Functionality:
Stacks provide only a limited set of operations (push, pop, peek), which may not be sufficient for all applications. More complex operations may require additional data structures or algorithms.