Stack Class in Java Programming.

In Java, the Collection Framework is a unified architecture that provides a set of interfaces, implementations, and algorithms to manipulate and store collections of objects. It provides standard implementations (like ArrayList, LinkedList, HashSet, etc) for these interfaces, catering to diverse data storage and manipulation needs. The java.util.Stack class is a part of this framework, offering a dynamic, resizable implementation of a Last In, First Out (LIFO) stack data structure.

Stack Class in Java.

Stack is a subclass of Vector and follows its structure, but it's designed for stack operations, providing methods specifically for stack functionalities. Despite being part of the Collection Framework, it's an older implementation, and its use is discouraged in favor of more modern alternatives like Deque implementations.

The Stack class supports essential operations like push, pop, peek, empty check, and determining size, mirroring traditional stack functionalities.

List of Basic Stack Operations:

  • push(element): Adds an element to the top of the stack.
  • pop(): Removes and returns the top element from the stack.
  • peek(): Returns the top element without removing it.
  • isEmpty(): Checks if the stack is empty.
  • search(element): Searches for an element in the stack and returns its position.

How To Use Stack Class in Java?

To create and use the stack in Java, you must import Stack Class from java.util package (java.util.stack) at the beginning of your Java file and instantiate a Stack object with the desired data type as shown below.

Example: Stack<Integer> myStack = new Stack<>(); 

Java Example Code:
// Java Stack Class Implementation code
import java.util.Stack;

public class StackOperationsExample {
    public static void main(String[] args) {
        // Creating a stack of integers
        Stack<Integer> myStack = new Stack<>();

        // Pushing elements onto the stack
        myStack.push(10);
        myStack.push(20);
        myStack.push(30);

        // Accessing the top element without removing it (peek)
        int topElement = myStack.peek();
        System.out.println("Top element: " + topElement);

        // Popping the top element
        int poppedElement = myStack.pop();
        System.out.println("Popped element: " + poppedElement);

        // Checking if the stack is empty
        boolean isEmpty = myStack.empty();
        System.out.println("Is stack empty? " + isEmpty);

        // Determining the size of the stack
        int stackSize = myStack.size();
        System.out.println("Size of stack: " + stackSize);

        // Search for an element in the stack
        int searchElement = 20;
        int position = myStack.search(searchElement);
        if (position != -1) {
            System.out.println("Element " + searchElement + " found at position: " + position);
        } else {
            System.out.println("Element " + searchElement + " not found in the stack");
        }
    }
}
Output:
Top element: 30
Popped element: 30
Is stack empty? false
Size of stack: 2Element 20 found at position: 1

In this above code, we have used integer stack to demonstrate the usage of stack operations in Java; similarly, you can create a stack for different data types. 
  • Time Complexity: push(), pop(), peek(), empty(), size() have constant time O(1) complexity. These operations generally perform in constant time regardless of the number of elements in the stack.
  • Space Complexity: The space complexity of the Stack in Java is O(n) where n is the number of elements in the stack.

The Stack class in Java offers a convenient way to implement a stack data structure with basic stack operations. While it follows the traditional stack behavior, it's recommended to use more efficient alternatives provided by the Collection Framework to enhance performance and versatility in modern Java programming.

Python Program to Subtract two Matrices.

Matrix subtraction is a fundamental operation in linear algebra and is often required in various scientific and computational applications. In this article, we'll explore how to subtract two matrices using Python programming.

In matrix subtraction, elements of one matrix are subtracted from their corresponding elements in another matrix of the same dimensions. The result is a new matrix with dimensions identical to the original matrices being subtracted. 

Quick Tip: Ensure matrices have the same dimensions for subtraction (m x n).

Matrix Subtraction Program in Python.

Step-by-step Algorithm:
  • Define two matrices A and B, each represented as nested lists in Python.
  • Create a new matrix to store the result of the subtraction.
  • Subtract corresponding elements of matrices A and B to obtain the elements of the resultant matrix.
  • Use nested loops to iterate through each element in the matrices and perform subtraction.

Python Code:

# Python code for matrix subtraction
def subtract_matrices(matrix_A, matrix_B):
    result_matrix = []
    for i in range(len(matrix_A)):
        row = []
        for j in range(len(matrix_A[0])):
            row.append(matrix_A[i][j] - matrix_B[i][j])
        result_matrix.append(row)
    return result_matrix

# Example usage
matrix_A = [[1, 2, 3],
            [4, 5, 6],
            [7, 8, 9]]

matrix_B = [[9, 8, 7],
            [6, 5, 4],
            [3, 2, 1]]

result = subtract_matrices(matrix_A, matrix_B)
print("Resultant Matrix after subtraction:")
for row in result:
    print(row)
Output:
Resultant Matrix after subtraction:
[-8, -6, -4]
[-2, 0, 2]
[4, 6, 8]
  • Time Complexity: O(m x n) where m is the number of rows and n is the number of columns.
  • Space Complexity: O(m x n) because we need extra space to store the resultant matrix.

Stack STL in C++.

Stack STL is a very useful tool when we have to work with Stack data structure in real programming because then we do not have to implement the complete stack from the beginning each time we use them in our code. But before learning Stack STL in detail let's get a short idea about C++ STL.

The Standard Template Library (STL) in C++ is a powerful collection of template classes and functions that provides a rich set of algorithms, containers, and functionalities to facilitate generic programming. It is a fundamental part of the C++ programming language, aiming to simplify and enhance code reusability, maintainability, and efficiency. 

What is Stack STL?

In the list of STL containers, we also have Stack STL which is a powerful tool that provides an efficient and easy-to-use implementation of the stack data structure. The std::stack class encapsulates the functionality of a stack, offering a convenient interface to manage data in a Last In, First Out (LIFO) manner.

std::stack abstracts the core stack operations (push, pop, top, isEmpty, and size) into intuitive member functions, simplifying the manipulation of elements in the stack. It is an adapter class that adapts an underlying container (like std::deque, std::vector, or std::list) to provide stack functionalities.

Functions Present in Stack STL.

The std::stack container adapter in C++ provides several functions to manipulate elements in a stack-like structure. Here are the functions available in std::stack:

stack.push(element): Adds an element to the top of the stack.
stack.pop(): Removes the top element from the stack.
stack.top(): Retrieves the top element from the stack without removing it.
stack.empty(): Checks if the stack is empty. Returns true if the stack is empty, else returns false.
stack.size(): Returns the number of elements in the stack.

Stack STL in C++ Program.

To use Stack STL in our code we first have to include <stack> header file and below is the syntax to declare a stack of specific type (e.g., integers).

Syntax: std::stack<dataType> myStack; 

C++ Code:
// C++ Code Example of Stack STL
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> myStack;

    // Pushing elements onto the stack
    myStack.push(10);
    myStack.push(20);
    myStack.push(30);

    // Accessing the top element
    cout << "Top element: " << myStack.top() << endl;

    // Popping the top element
    myStack.pop();

    // Checking if the stack is empty
    if (myStack.empty()) {
        cout << "Stack is empty\n";
    } else {
        cout << "Stack is not empty\n";
    }

    // Determining the size of the stack
    cout << "Size of stack: " << myStack.size() << endl;

    return 0;
}
Output:
Top element: 30
Stack is not empty
Size of stack: 2

Time and Space Complexity.

  • Time Complexity: push(), pop(), top(), empty(), and size() have constant time complexity O(1) regardless of the number of elements in the stack.
  • Space Complexity: The space complexity of std::stack mainly depends on the underlying container used. By default, it uses std::deque as its underlying container, which typically allocates memory in blocks. Therefore, the space complexity can be considered as O(n).

Mostly while problem-solving and in real-world applications we use STL of different data structures instead of building it from the beginning and we also encourage you to learn and use them in your code to make it more efficient but at the same time, you all should know the basic principle and working of stack and other data structure.

How To Change Keyboard Language in Windows 11.

Poster of Change Windows 11 Default Language

Changing the keyboard language in Windows 11 can be essential for multilingual users or those who prefer a different input method. Here's a detailed guide on how to seamlessly switch and, if needed, remove keyboard languages on your Windows 11 system.

How To Change Keyboard Language in Windows.

In the initial setup of Windows 11, you'll be prompted to select your primary keyboard language, which will serve as the default setting for your computer. Nevertheless, the Windows Settings app provides a straightforward method to change this language repertoire by installing additional keyboard languages. This allows you to seamlessly switch between different languages.

Below are the steps that you need to follow to add another language to your keyboard:

Step 1: Open Windows Settings, Click on the Start menu, and select the gear-shaped icon for "Settings."

Settings Option in Windows

Step 2: In the Settings window, choose "Time & Language" from the left sidebar and select Language & Region.

Time & Language Setting in Windows

Step 3: Under the "Preferred languages" section, click on "Add a language."

Adding a Language in Windows 11

Step 4: Scroll through the list of available languages, select the one you want to add, and click "Next."

Next Button to Select Language in Windows

Step 5: If the language supports multiple keyboard layouts, choose the specific layout you prefer and click "Install."

Installing new language keyboard

Step 6: Once installed, you can set the newly added language as the default by clicking on it and selecting "Set as default."

Step 7: To change the keyboard language while typing, press the "Windows key + Spacebar" to cycle through the installed languages or you can click the language icon in the taskbar to choose the language you want to use.

Choosing Language from Windows Taskbar
Quick Tip: You can enable the Language Bar for quick access to language settings. In Language settings, go to "Advanced keyboard settings" and turn on the "Use the desktop language bar when it's available." (alert-success)
Quick Tip: Customize a shortcut key for easy switching between languages. In Language settings, go to "Advanced keyboard settings" and under "Switching input methods," click on "Change language bar hot keys." (alert-success)

How To Remove Keyboard Language in Windows.

If you've added a language you no longer require and want to change your language presence, removing it is a straightforward process. Below is a step-by-step guide on how to remove a keyboard language from your Windows 11 system.

 

Step 1: Click on the Start button or press the Windows key, and select the "Settings" icon (gear-shaped) on the left side of the Start menu.


Step 2: In the Settings menu, select "Time & Language" from the left sidebar and click on "Language & region".


Step 3: Scroll down to the section labeled Preferred languages and click on the language you want to remove. 

Remove Language from Windows Keyboard

Step 4: Once you've selected the language, click on the three-dot options button that appears on the right and click on "Remove".


Step 5: A confirmation window will pop up asking if you want to remove the language. Click on "Remove" to confirm your action.

Uninstall Language from Windows Setting

Quick Tip: If you're removing a language that was set as the default input, Windows will automatically switch to the next available language in the list. (alert-success)

Applications of Stack Data Structure.

The stack is a linear data structure that operates on the Last In, First Out (LIFO) principle, which means whatever data is inserted at last in the stack will come out first. Imagine it like a stack of plates where the last plate placed is the first one to be removed from the top. A stack can be visualized as a collection of elements stacked on top of each other, allowing two primary operations: push and pop.

When an element is pushed onto the stack, it becomes the new top element. Subsequent pushes place new element on the top, effectively forming a sequence. The pop operation removes the top element, revealing the next element in the stack. This behavior ensures that the most recently added item is always the first to be removed as the insertion and deletion of an element happens from the same end (top).  

Additionally, a stack supports other operations like peek, enabling us to view the top element without removing it, and methods to determine whether the stack is empty (isEmpty) and to know its current size (size)

A stack can be implemented using either an array or linked lists. Arrays offer simplicity and constant-time access to elements but have a fixed size, whereas linked lists provide flexibility in size but might involve more memory overhead due to their node structure. 

Read our detailed article on stack data structure to understand the implementation in detail.

List of Common Stack Operations:

  • push(element): Adds an element to the top of the stack.
  • pop(): Removes and returns the element from the top of the stack.
  • peek() or top(): Returns the element at the top of the stack without removing it.
  • isEmpty(): Checks if the stack is empty.
  • size(): Determines the number of elements in the stack.
These operations are fundamental for managing and manipulating elements within a stack.
Operations of Stack Data structure
Stack Data Structure

Exploring Applications of Stack Data Structure.

Stack is a fundamental data structure in computer science, and finds its utility across a wide array of applications. 

1. Function Calls and Recursion: 

Stacks play a crucial role in managing function calls in programming languages. When a function is called, its context, including local variables and execution point, is pushed onto the call stack. As subsequent functions are called or when recursion occurs, new contexts are stacked on top. Upon returning from a function or completing recursion, the corresponding context is popped off the stack, allowing the program to resume execution from the previous point.

2. Expression Evaluation: 

In evaluating mathematical expressions, stacks are used to handle parentheses, operators, and operands. The infix-to-postfix conversion and postfix expression evaluation utilize stacks to ensure proper sequencing and precedence of operations.

3. Undo Mechanisms in Text Editors: 

Text editors often implement undo functionalities using stacks. Each edit operation is pushed onto the stack, allowing users to revert changes sequentially. When the undo command is invoked, the most recent edit is popped off the stack, effectively undoing the action.

4. Browser History in Web Browsing: 

The back/forward functionality in web browsers uses stacks. Visited web pages are pushed onto the history stack. Clicking the back button pops the last visited page, simulating the LIFO behavior of a stack.

5. Memory Management in Operating Systems: 

Operating systems utilize stacks for memory management. The system stack, responsible for managing function calls and storing local variables, follows the stack data structure model. Additionally, the call stack helps in managing memory allocation and deallocation through its LIFO nature.

Advantages of Stack Data Structure.

  • Stacks are simple to implement and understand, making them easy to use in various applications.
  • They offer efficient data retrieval and storage for specific operations like push, pop, and peek, with a constant time complexity O(1).
  • Stacks support automatic memory management, especially in programming languages that use stack-based memory allocation and deallocation.
  • Stacks are useful for reversing a sequence of elements efficiently due to their LIFO behavior.

Disadvantages of Stack Data Structure.

  • Stack provides limited access to elements. Direct access to arbitrary elements, other than the top one, is not possible without sequentially popping off elements.
  • If implemented using arrays, stacks have a fixed maximum capacity, making them prone to overflow issues when trying to add elements beyond the size limit.
  • Stack is not a suitable data structure for performing certain operations like searching and sorting as it is difficult to change the order of stack elements.

Difference Between Stack and Queue Data Structure.

Data structures are fundamental components in computer science that organize and store data efficiently, enabling easy access, insertion, deletion, and manipulation of data elements. Two essential data structures in this domain are stacks and queues. In this article, we will understand the difference between them and which one we should use in which condition.

Stack Data Structure.

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle which means the insertion (push) and deletion (pop) happen only from one side of the stack which is the top. The last element pushed onto the stack is the first to be popped off. Let's understand stack data structure with one real-life example:

Example:
Consider a practical scenario: browsing the internet. Your browser's back button functionality perfectly illustrates how a stack operates. When you visit the web pages, each visited page becomes analogous to a plate added to a stack. The most recently visited page sits on top, while the older pages form a stack beneath it. 

As you navigate through these pages, you often use the back button to revisit previously viewed pages. This action mimics the operation of a stack: when you press 'back' the last page (the most recent addition to the stack) gets popped off the stack and becomes the current page.

Operations of Stack Data Structure
Stack Data Structure

Queue Data Structure.

A Queue is a linear data structure that operates on the principle of First In, First Out (FIFO), which means the element that is inserted first in the queue will out first from the queue. Elements are added at the rear end (enqueue) and removed from the front (dequeue), making it efficient for scenarios where data needs to be processed in the order it was received. Let's understand the queue data structure with one real-life example:

Example:
Consider a printer queue handling multiple print jobs, as documents are sent for printing, they join the queue. The printer processes these documents in the order they arrive. Similarly, in programming, a queue is used to manage data based on their arrival sequence.

Operations for Queue Data Structure
Queue Data Structure

Difference Between Stack and Queue.

Stacks Queues
Stack is based on the Last In, First Out (LIFO) principle, elements that are inserted first will come out at last. A Queue is based on the First In, First Out (FIFO) principle, elements that are inserted first in the queue will come out first.
In stack, the insertion operation is known as the "Push" operation. A queue insertion operation is known as an "Enqueue" operation.
In stack deletion operation is known as "Pop" operation. In queue deletion operation is known as "Dequeue" operation.
In stack, access to elements is limited to the top element (or the element at the end). In a queue, access to elements is limited to the front element (or the element at the beginning)
In stack, data moves in and out from the same end. In queue, data enters from the rear and exits from the front.
It can be implemented using arrays or linked lists. It can be implemented using arrays or linked lists.
Example: Browser history, call stack in programming, backtracking algorithms. Example: Print queue, task scheduling in operating systems, and breadth-first search algorithms.

Similarities of Stack and Queue Data Structure.

Although stack and queue are completely two different data structures still they share a few similarities:
  • Both stacks and queues are linear data structures where elements are stored in a sequential manner.
  • They support common operations like isEmpty to check if the structure is empty, size to determine the number of elements, and peek to view the top/front element without removing it.
  • Both structures can be implemented using arrays or linked lists to manage and organize their elements.

Introduction to Stack Data Structure.

What is a Stack?

A stack is a linear data structure that operates on the principle of Last In, First Out (LIFO). This means that the last element added to the stack is the first one to be removed.


Imagine a stack of books. When you add a new book, it goes on top of the pile. To access the books, you start from the top and the last book you place on the top of the stack is the first one you'll pick up. Similarly, in a stack data structure, elements are added or removed only from the top position.


LIFO (Last-In, First Out).

The Last In, First Out (LIFO) property of a stack refers to the characteristic where the most recently added item is the first one to be removed. In simpler terms, the element that is pushed (added) last onto the stack will be the first one to be popped (removed) from the stack.

Stack Operations
Stack Data Structure

Basic Operation on Stack Data Structure.

There are certain functions and operations available for the stack data structure that are very useful for us.

  • push(): This function adds an element to the top of the stack. 
  • pop(): This function is used to remove the top element from the stack.
  • peek() or top(): This function is used to view the top element of the stack without removing it. 
  • isEmpty(): This function returns true if the stack is empty else, it returns false.
  • size(): This function returns the size of the stack.

Time Complexity of Stack Operations.

Function Time Complexity Explanation
push() O(1) Adding an element to the top of the stack takes constant time because it involves simply updating the top pointer or adding a new node.
pop() O(1) Removing an element from the top of the stack also takes constant time. It involves updating the top pointer or removing a node from the beginning of the linked list.
peek() O(1) Viewing the top element without removing it is a constant-time operation. It requires accessing the top element which can be done directly without iteration.
isEmpty() O(1) Checking if the stack is empty or not takes a constant amount of time because we just have to check if any element is present inside the stack or not.
size() O(1) Getting the size of the stack takes a constant amount of time because we already know the position of the top element which helps us to find the size of the stack.

Real-World Use of Stack Data Structure.

The principle of  Stack data structure is used in various scenarios:
  • Function Calls in Programming: When a function is called, its execution (variables, parameters, etc.) is added to the call stack. As functions complete execution, they are removed from the stack. This enables tracking the flow of the function calls and their respective return addresses.
  • Browser History: Navigating web pages creates a history, much like a stack. Each page visited is added to the history stack. The back button operates by removing the last page visited (the top of the stack).
  • Text Editor Undo Functionality: The undo feature in text editors uses a stack-like structure. Each action performed (typing, deleting, formatting) is recorded as a step in the stack. The undo operation reverses the most recent action by popping it off the stack.
  • Expression Evaluation: In programming, evaluating mathematical expressions involves using a stack. For instance, converting an infix expression (2 + 3) * 4 into a postfix uses a stack to maintain operator precedence.

Types of Stack.

There are two main types of stacks static and dynamic. 

Stack Stack: A static stack is a fixed-size stack, where the maximum capacity of the stack is determined and allocated during compile time. It is usually implemented using arrays due to their fixed-size characteristics. Once the size of the stack is defined, it cannot be changed during runtime.

Pros:

  • Easy to implement using arrays with fixed sizes.
  • Direct access to elements provides fast retrieval.
  • Predictable size allows for better memory management.
Cons:
  • Restricted to the predefined size, leading to potential overflow issues if the stack exceeds its capacity.
  • If the stack doesn't reach its full capacity, there might be wasted memory due to the fixed allocation.

Dynamic Stack: A dynamic stack adjusts its size dynamically during runtime based on the number of elements it holds. It is commonly implemented using dynamically allocated memory, like linked lists, to allow resizing.

Pros:

  • Accommodates varying numbers of elements without a predefined limit.
  • Efficiently utilizes memory by resizing as required.
  • Adjusts dynamically, minimizing the risk of overflow or underflow errors.
Cons:
  • More complex to implement compared to static stacks, especially when using linked lists.
  • Dynamic resizing operations may lead to memory fragmentation issues over time.

Implementation of Stack.

A stack can be implemented using other linear data structures like an array or linked list. Both have their own advantages and disadvantages. Let's discuss each of them one by one in detail. 

Pseudocode for Stack Implementation.

Stack Initialization:
    Stack[max_size]   // Initialize stack with a maximum size
    top = -1          // Initialize top pointer to -1 (empty stack)
    
Push(Stack, element):
    if top == max_size - 1:
        return "Overflow error"
    else:
        increment top
        Stack[top] = element

Pop(Stack):
    if top == -1:
        return "Underflow error"
    else:
        removed_element = Stack[top]
        decrement top
        return removed_element

Peek(Stack):
    if top == -1:
        return "Stack is empty"
    else:
        return Stack[top]

IsEmpty(Stack):
    return top == -1

Size(Stack):
    return top + 1

Stack Implementation Using Arrays.

Arrays offer a straightforward implementation for stacks. They provide direct access to elements using indices, making operations like push and pop relatively simple. Accessing elements by index allows faster retrieval of elements compared to linked lists, as arrays offer constant-time access.

Code Implementation:
// C++ Code implementation of stack operations
#include <iostream>
using namespace std;

const int MAX_SIZE = 100; // Maximum stack size

class StackArray {
private:
    int stack[MAX_SIZE];
    int top;

public:
    StackArray() {
        top = -1; // Initializing top to -1 for an empty stack
    }

    void push(int element) {
        if (top == MAX_SIZE - 1) {
            cout << "Stack Overflow" << endl;
            return;
        }
        top++;
        stack[top] = element;
    }

    int pop() {
        if (top == -1) {
            cout << "Stack Underflow" << endl;
            return -1; // Assuming -1 as an error value for an empty stack
        }
        int element = stack[top];
        top--;
        return element;
    }

    int peek() {
        if (top == -1) {
            cout << "Stack is empty" << endl;
            return -1; // Assuming -1 as an error value for an empty stack
        }
        return stack[top];
    }

    bool is_empty() {
        return top == -1;
    }

    int size() {
        return top + 1;
    }
};

int main() {
    StackArray stack;
    stack.push(5);
    stack.push(10);
    stack.push(15);

    cout << "Top of the stack: " << stack.peek() << endl;

    stack.pop();
    cout << "Top of the stack after pop: " << stack.peek() << endl;

    cout << "Is the stack empty? " << (stack.is_empty() ? "Yes" : "No") << endl;

    cout << "Current size of the stack: " << stack.size() << endl;

    return 0;
}
// Java code implementation of stack operations

public class StackArray {
  private int[] stack;
  private int top;
  private int maxSize;

  public StackArray(int maxSize) {
      this.maxSize = maxSize;
      this.stack = new int[maxSize];
      this.top = -1; // Initializing top to -1 for an empty stack
  }

  public void push(int element) {
      if (top == maxSize - 1) {
          System.out.println("Stack Overflow");
          return;
      }
      top++;
      stack[top] = element;
  }

  public int pop() {
      if (top == -1) {
          System.out.println("Stack Underflow");
          return -1; // Assuming -1 as an error value for an empty stack
      }
      int element = stack[top];
      top--;
      return element;
  }

  public int peek() {
      if (top == -1) {
          System.out.println("Stack is empty");
          return -1; // Assuming -1 as an error value for an empty stack
      }
      return stack[top];
  }

  public boolean isEmpty() {
      return top == -1;
  }

  public int size() {
      return top + 1;
  }

  public static void main(String[] args) {
      StackArray stack = new StackArray(5);
      stack.push(5);
      stack.push(10);
      stack.push(15);

      System.out.println("Top of the stack: " + stack.peek());

      stack.pop();
      System.out.println("Top of the stack after pop: " + stack.peek());

      System.out.println("Is the stack empty? " + (stack.isEmpty() ? "Yes" : "No"));

      System.out.println("Current size of the stack: " + stack.size());
  }
}
# Python code implementation of stack operations
class StackArray:
def __init__(self):
    self.MAX_SIZE = 100  # Maximum stack size
    self.stack = [None] * self.MAX_SIZE
    self.top = -1  # Initializing top to -1 for an empty stack

def push(self, element):
    if self.top == self.MAX_SIZE - 1:
        print("Stack Overflow")
        return
    self.top += 1
    self.stack[self.top] = element

def pop(self):
    if self.top == -1:
        print("Stack Underflow")
        return None  # Assuming None as an error value for an empty stack
    element = self.stack[self.top]
    self.top -= 1
    return element

def peek(self):
    if self.top == -1:
        print("Stack is empty")
        return None  # Assuming None as an error value for an empty stack
    return self.stack[self.top]

def is_empty(self):
    return self.top == -1

def size(self):
    return self.top + 1

# Test the StackArray class
stack = StackArray()
stack.push(5)
stack.push(10)
stack.push(15)

print("Top of the stack:", stack.peek())

stack.pop()
print("Top of the stack after pop:", stack.peek())

print("Is the stack empty?", "Yes" if stack.is_empty() else "No")

print("Current size of the stack:", stack.size())
// C# Code for stack implementation
using System;

public class StackArray {
    private int[] stack;
    private int top;
    private int maxSize;

    public StackArray(int maxSize) {
        this.maxSize = maxSize;
        this.stack = new int[maxSize];
        this.top = -1; // Initializing top to -1 for an empty stack
    }

    public void Push(int element) {
        if (top == maxSize - 1) {
            Console.WriteLine("Stack Overflow");
            return;
        }
        top++;
        stack[top] = element;
    }

    public int Pop() {
        if (top == -1) {
            Console.WriteLine("Stack Underflow");
            return -1; // Assuming -1 as an error value for an empty stack
        }
        int element = stack[top];
        top--;
        return element;
    }

    public int Peek() {
        if (top == -1) {
            Console.WriteLine("Stack is empty");
            return -1; // Assuming -1 as an error value for an empty stack
        }
        return stack[top];
    }

    public bool IsEmpty() {
        return top == -1;
    }

    public int Size() {
        return top + 1;
    }

    public static void Main() {
        StackArray stack = new StackArray(5);
        stack.Push(5);
        stack.Push(10);
        stack.Push(15);

        Console.WriteLine("Top of the stack: " + stack.Peek());

        stack.Pop();
        Console.WriteLine("Top of the stack after pop: " + stack.Peek());

        Console.WriteLine("Is the stack empty? " + (stack.IsEmpty() ? "Yes" : "No"));

        Console.WriteLine("Current size of the stack: " + stack.Size());
    }
}
Output:
Top of the stack: 15
Top of the stack after pop: 10
Is the stack empty? No
Current size of the stack: 2

Advantages of  Stack Implementation using Array:
  • Direct indexing in arrays enables quick element retrieval.
  • Arrays offer straightforward implementation of stacks.
  • They generally use less memory due to direct storage.

Disadvantages of Stack Implementation using Array:
  • Arrays have a limited size, hindering maximum capacity.
  • Adjusting array size is resource-intensive.
  • Unused space in arrays can lead to inefficiency.

Stack Implementation Using Linked_List.

Linked lists allow for dynamic memory allocation which helps us add many stack elements without a predetermined maximum capacity, which overcomes the limitation of fixed-size arrays. Unlike arrays, linked lists do not require resizing when accommodating more elements. Each new node can be dynamically allocated as needed.

Code Implementation:
// C++ code to implementation stack operation using linked list
#include <iostream>
using namespace std;

// Node structure to represent elements in the linked list
struct Node {
    int data;
    Node* next;
};

class StackLinkedList {
private:
    Node* top; // Pointer to the top node of the stack

public:
    StackLinkedList() {
        top = nullptr; // Initializing top to null for an empty stack
    }

    // Function to push an element onto the top of the stack
    void push(int element) {
        Node* newNode = new Node(); // Creating a new node
        newNode->data = element;
        newNode->next = top;
        top = newNode; // Updating top to point to the new node
    }

    // Function to pop an element from the top of the stack
    int pop() {
        if (top == nullptr) {
            cout << "Stack Underflow" << endl;
            return -1; // Assuming -1 as an error value for an empty stack
        }
        Node* temp = top;
        int element = temp->data;
        top = top->next;
        delete temp; // Freeing memory of the popped node
        return element;
    }

    // Function to peek at the top element without removing it
    int peek() {
        if (top == nullptr) {
            cout << "Stack is empty" << endl;
            return -1; // Assuming -1 as an error value for an empty stack
        }
        return top->data;
    }

    // Function to check if the stack is empty
    bool isEmpty() {
        return top == nullptr;
    }

    // Function to determine the size of the stack
    int size() {
        int count = 0;
        Node* current = top;
        while (current != nullptr) {
            count++;
            current = current->next;
        }
        return count;
    }
};

int main() {
    StackLinkedList stack;
    stack.push(5);
    stack.push(10);
    stack.push(12);
    stack.push(15);

    cout << "Top of the stack: " << stack.peek() << endl;

    stack.pop();
    cout << "Top of the stack after pop: " << stack.peek() << endl;

    cout << "Is the stack empty? " << (stack.isEmpty() ? "Yes" : "No") << endl;

    cout << "Current size of the stack: " << stack.size() << endl;

    return 0;
}
// Java code for stack implementation using linkedlist
public class StackLinkedList {
    private Node top;

    // Inner Node class
    private class Node {
        int data;
        Node next;

        Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    public StackLinkedList() {
        top = null;
    }
    // function to add element in the stack
    public void push(int element) {
        Node newNode = new Node(element);
        newNode.next = top;
        top = newNode;
    }
    // function to remove element from stack
    public int pop() {
        if (top == null) {
            System.out.println("Stack Underflow");
            return -1; // Assuming -1 as an error value for an empty stack
        }
        int element = top.data;
        top = top.next;
        return element;
    }
    // function to view top element of stack
    public int peek() {
        if (top == null) {
            System.out.println("Stack is empty");
            return -1; // Assuming -1 as an error value for an empty stack
        }
        return top.data;
    }
    // function to check if stack is empty
    public boolean isEmpty() {
        return top == null;
    }
    // function to get stack size
    public int size() {
        int count = 0;
        Node current = top;
        while (current != null) {
            count++;
            current = current.next;
        }
        return count;
    }

    public static void main(String[] args) {
        StackLinkedList stack = new StackLinkedList();
        stack.push(5);
        stack.push(10);
        stack.push(12);
        stack.push(15);

        System.out.println("Top of the stack: " + stack.peek());

        stack.pop();
        System.out.println("Top of the stack after pop: " + stack.peek());

        System.out.println("Is the stack empty? " + (stack.isEmpty() ? "Yes" : "No"));

        System.out.println("Current size of the stack: " + stack.size());
    }
}
# Python code implementation of stack using linked list 
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class StackLinkedList:
    def __init__(self):
        self.top = None
    
    # function to add element in stack
    def push(self, element):
        new_node = Node(element)
        new_node.next = self.top
        self.top = new_node
    
    # function to remove element from the stack
    def pop(self):
        if self.top is None:
            print("Stack Underflow")
            return -1  # Assuming -1 as an error value for an empty stack
        element = self.top.data
        self.top = self.top.next
        return element
    
    # function to view top element of stack
    def peek(self):
        if self.top is None:
            print("Stack is empty")
            return -1  # Assuming -1 as an error value for an empty stack
        return self.top.data
    
    # function to check if stack is empty
    def is_empty(self):
        return self.top is None
    
    # function to get stack size
    def size(self):
        count = 0
        current = self.top
        while current is not None:
            count += 1
            current = current.next
        return count

# Test the StackLinkedList class
stack = StackLinkedList()
stack.push(5)
stack.push(10)
stack.push(12)
stack.push(15) print("Top of the stack:", stack.peek()) stack.pop() print("Top of the stack after pop:", stack.peek()) print("Is the stack empty?", "Yes" if stack.is_empty() else "No") print("Current size of the stack:", stack.size())
// C# code implementation of stack using linked list
using System;

public class StackLinkedList {
    private Node top; // Top node of the stack

    // Node class representing elements in the linked list
    private class Node {
        public int data;
        public Node next;

        public Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    public StackLinkedList() {
        top = null; // Initializing top to null for an empty stack
    }
    // function to add element in stack
    public void Push(int element) {
        Node newNode = new Node(element); // Creating a new node
        newNode.next = top;
        top = newNode; // Updating top to point to the new node
    }

    // function to remove element from the stack
    public int Pop() {
        if (top == null) {
            Console.WriteLine("Stack Underflow");
            return -1; 
        }
        int element = top.data;
        top = top.next;
        return element;
    }

    // function to view top element of stack
    public int Peek() {
        if (top == null) {
            Console.WriteLine("Stack is empty");
            return -1; 
        }
        return top.data;
    }
    
    // function to check if stack is empty
    public bool IsEmpty() {
        return top == null;
    }

    // function to get the size of the stack
    public int Size() {
        int count = 0;
        Node current = top;
        while (current != null) {
            count++;
            current = current.next;
        }
        return count;
    }

    public static void Main() {
        StackLinkedList stack = new StackLinkedList();
        stack.Push(5);
        stack.Push(10);
        stack.Push(12);
        stack.Push(15);

        Console.WriteLine("Top of the stack: " + stack.Peek());

        stack.Pop();
        Console.WriteLine("Top of the stack after pop: " + stack.Peek());

        Console.WriteLine("Is the stack empty? " + (stack.IsEmpty() ? "Yes" : "No"));

        Console.WriteLine("Current size of the stack: " + stack.Size());
    }
}
Output:
Top of the stack: 15
Top of the stack after pop: 12
Is the stack empty? No
Current size of the stack: 3

Advantages of Stack Implementation using Linked List.
  • Linked lists adapt to varying element counts without a fixed maximum limit.
  • They don't have predefined size limitations, offering flexibility.
  • Allocate memory as needed, minimizing wastage.
  • Allows efficient element addition/removal without resizing.

Disadvantages of Stack Implementation using Linked List.
  • Extra memory is used for maintaining pointers.
  • Sequential access impacts direct element retrieval.
  • Traversal can be slower for larger lists.

Both implementations follow the same fundamental principles of maintaining the LIFO behavior and providing operations for manipulating the stack. You can also check the comparison between stack and queue data structures to understand the situation in which we use Stacks.

DON'T MISS

Nature, Health, Fitness
© all rights reserved
made with by templateszoo