stack Algorithm

The stack using a doubly linked list (DLL) algorithm is a dynamic data structure that stores a collection of elements in a linear fashion, where each element has a reference to the element before and after it. This stack allows for the efficient management of elements by performing insertions and deletions at the beginning or end of the list without affecting the rest of the elements. A commonly used analogy to describe a stack is a stack of plates, where you can only add or remove a plate from the top of the stack. This behavior is known as Last-In, First-Out (LIFO), which means that the most recently added element is always the first one to be removed. Implementing a stack using a doubly linked list offers several advantages over other data structures like arrays. First, it allows for dynamic resizing, which means that the stack can grow or shrink in size as elements are added or removed. This makes it more memory-efficient, as the stack only uses the exact amount of memory needed to store its elements. Second, the time complexity for inserting and deleting elements in a DLL-based stack is O(1), which makes these operations quite fast. However, this comes at the cost of increased complexity in managing the pointers for the previous and next elements in the list, which can make the implementation more challenging than using an array-based stack.
__author__ = "Omkar Pathak"


class Stack:
    """ A stack is an abstract data type that serves as a collection of
    elements with two principal operations: push() and pop(). push() adds an
    element to the top of the stack, and pop() removes an element from the top
    of a stack. The order in which elements come off of a stack are
    Last In, First Out (LIFO).

    https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
    """

    def __init__(self, limit=10):
        self.stack = []
        self.limit = limit

    def __bool__(self):
        return bool(self.stack)

    def __str__(self):
        return str(self.stack)

    def push(self, data):
        """ Push an element to the top of the stack."""
        if len(self.stack) >= self.limit:
            raise StackOverflowError
        self.stack.append(data)

    def pop(self):
        """ Pop an element off of the top of the stack."""
        if self.stack:
            return self.stack.pop()
        else:
            raise IndexError("pop from an empty stack")

    def peek(self):
        """ Peek at the top-most element of the stack."""
        if self.stack:
            return self.stack[-1]

    def is_empty(self):
        """ Check if a stack is empty."""
        return not bool(self.stack)

    def size(self):
        """ Return the size of the stack."""
        return len(self.stack)

    def __contains__(self, item) -> bool:
        """Check if item is in stack"""
        return item in self.stack


class StackOverflowError(BaseException):
    pass


if __name__ == "__main__":
    stack = Stack()
    for i in range(10):
        stack.push(i)

    print("Stack demonstration:\n")
    print("Initial stack: " + str(stack))
    print("pop(): " + str(stack.pop()))
    print("After pop(), the stack is now: " + str(stack))
    print("peek(): " + str(stack.peek()))
    stack.push(100)
    print("After push(100), the stack is now: " + str(stack))
    print("is_empty(): " + str(stack.is_empty()))
    print("size(): " + str(stack.size()))
    num = 5
    if num in stack:
        print(f"{num} is in stack")

LANGUAGE:

DARK MODE: