Data Structures and Algorithms in JavaScript : Stack
A Stack is a linear data structure in computer science that follows the Last-In-First-Out (LIFO) principle. In a stack, the most recently added item is the first to be removed. Think of it as a collection of items arranged like a stack of plates. You add new plates to the top of the stack, and when you want to remove a plate, you take it from the top.
Key characteristics of a stack:
1. **Push:** This operation adds an element to the top of the stack.
2. **Pop:** This operation removes and returns the top element of the stack.
3. **Peek (or Top):** This operation retrieves, but does not remove, the top element of the stack.
4. **IsEmpty:** This operation checks if the stack is empty.
5. **Size:** This operation returns the number of elements in the stack.
Stacks are commonly used in various computer algorithms and applications, such as parsing expressions, implementing function call management in programming languages (call stack), and backtracking algorithms. They provide a way to manage data in a last-in, first-out manner, which is particularly useful for keeping track of the most recent elements or operations.
Stacks are a fundamental data structure in computer science with several advantages and disadvantages based on their characteristics and use cases:
**Pros of Stacks:**
1. **Simple and Efficient:** Stacks are easy to implement and are typically quite efficient for their core operations (push and pop).
2. **LIFO Order:** The Last-In-First-Out (LIFO) order of stacks is suitable for various scenarios where you need to track the most recent elements or operations, such as function call management and undo functionality.
3. **Recursive Algorithms:** Stacks are used for tracking function calls in recursive algorithms, which simplifies the handling of nested function calls.
4. **Memory Management:** Stacks are crucial for managing memory in programming languages. The call stack is used to store information about function calls, local variables, and return addresses.
5. **Expression Evaluation:** Stacks are used in expression evaluation and parsing, such as in the evaluation of postfix expressions.
**Cons of Stacks:**
1. **Limited Access:** Stacks provide limited access to their elements. You can only access the top element, making them unsuitable for scenarios that require random access to elements.
2. **Inefficient for Some Operations:** While stacks are efficient for push and pop operations, they are not suitable for other operations, such as searching for a specific element.
3. **Fixed Size (in some implementations):** In some implementations of stacks, the size may be fixed, leading to potential overflow or underflow errors.
4. **Not Suitable for All Use Cases:** Stacks are not the best choice for every data processing task. For tasks requiring a different order or access pattern, other data structures like queues or arrays might be more appropriate.
In summary, stacks are valuable for scenarios where you need to manage data in a Last-In-First-Out (LIFO) order, particularly when tracking function calls, undoing operations, or evaluating expressions. However, they may not be the right choice for tasks that require random access to elements or a different order of processing. Your choice of data structure should be based on the specific requirements of your problem.
Implementation of Stack (using Classes).
(1) Creating a Stack.
class Stack {
constructor() {
this.items = [];
}
(2) Push: Add an element to the top of the stack.
push(item) {
this.items.push(item);
}
(3) Pop: Remove and return the top element from the stack.
pop() {
if (this.isEmpty()) {
return "Stack is empty";
}
return this.items.pop();
}
(4) Peek (or Top): Retrieve the top element without removing it.
peek() {
if (this.isEmpty()) {
return "Stack is empty";
}
return this.items[this.items.length - 1];
}
(5) isEmpty: Check if the stack is empty.
isEmpty() {
return this.items.length === 0;
}
(6) Size: Get the size of the stack.
size() {
return this.items.length;
}
}
Example:
const myStack = new Stack();
myStack.push(1);
myStack.push(2);
myStack.push(3);
console.log(myStack.pop()); // 3
console.log(myStack.peek()); // 2
console.log(myStack.size()); // 2