Queue Sandbox

# -*- coding: utf-8 -*-
"""qandstack.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1Nr_QNCQNn2BqTil9swxDWfpsBcdumEbQ

# Queues and Stacks

## Queue
- think of a queue as a line of people queing up to be served
- FIFO (First In First Out)

## Stack
- think of a stack as a stack of recipts on a nail or pin
- LIFO (Last In First Out)

What data structure could be of use as an underlying data storage for a stack or queue?
"""

# lets write a simple stack
class Stack:
    def __init__(self):
        self.storage = []

    def push(self, item):
        """
    push the item on to the top of the stack
    """
        self.storage.append(item)

    def pop(self):
        """
    pop the item from the top of the stack returning said item if there is anything on the stack.
    otherwise return "The Stack is Empty"
    """
        if len(self.storage) > 0:
            return self.storage.pop()
        return "The Stack is Empty"

    def peek(self):
        if len(self.storage) > 0:
            return self.storage[-1]
        return "The Stack is Empty"


s = Stack()
s.push(10)
s.push(20)
s.push(30)
l = []
l.append(s.pop())
l.append(s.pop())
l.append(s.pop())
print(l)

# lets write a simple queue
class Queue:
    def __init__(self):
        self.storage = []

    def enqueue(self, item):
        """
    enqueues the item in to the queue
    """
        self.storage.append(item)

    def dequeue(self):
        """
    dequeue the item from the front of the queue returning said item if there is anything on the queue.
    otherwise return "The Queue is Empty"
    """
        if len(self.storage) > 0:
            return self.storage.pop(0)
        return "The Queue is Empty"


q = Queue()
q.enqueue(10)
q.enqueue(20)
q.enqueue(30)

l2 = []
l2.append(q.dequeue())
l2.append(q.dequeue())
l2.append(q.dequeue())

print(l2)

# lets write a more performant queue
"""
  F      R
[10]-> [20]-> None
"""


class LLNode:
    def __init__(self, data):
        self.data = data
        self.next = None

    def __repr__(self):
        return f"[{self.data}]"


class LLQueue:
    def __init__(self):
        self.front = None
        self.rear = None

    def enqueue(self, item):
        new_node = LLNode(item)

        if self.rear is None:
            self.front = new_node
            self.rear = new_node
        else:
            self.rear.next = new_node
            self.rear = new_node

    def dequeue(self):
        old_front = "The Queue is Empty"
        if self.front is not None:
            old_front = self.front
            self.front = old_front.next

        if self.front is None:
            self.rear = None

        return old_front


q = LLQueue()
q.enqueue(10)
q.enqueue(20)
q.enqueue(30)

l2 = []
l2.append(q.dequeue())
l2.append(q.dequeue())
l2.append(q.dequeue())
l2.append(q.dequeue())

print(l2)

"""# Break
# CODE 8119
"""

# lets write a more performant stack
class LLNode:
    def __init__(self, data):
        self.data = data
        self.next = None

    def __repr__(self):
        return f"[{self.data}]"


class LLStack:
    def __init__(self):
        self.top = None

    def push(self, data):
        new_node = LLNode(data)
        new_node.next = self.top
        self.top = new_node

    def pop(self):
        if self.top is not None:
            poped_node = self.top
            self.top = poped_node.next

            return poped_node
        else:
            return "The Stack is Empty"


"""# Demos"""

"""
You've encountered a situation where you want to easily be able to pull the
largest integer from a stack.
You already have a `Stack` class that you've implemented using a dynamic array.
Use this `Stack` class to implement a new class `MaxStack` with a method
`get_max()` that returns the largest element in the stack. `get_max()` should
not remove the item.
*Note: Your stacks will contain only integers. You should be able to get a
runtime of O(1) for push(), pop(), and get_max().*
"""


class Stack:
    def __init__(self):
        """Initialize an empty stack"""
        self.items = []

    def push(self, item):
        """Push a new item onto the stack"""
        self.items.append(item)

    def pop(self):
        """Remove and return the last item"""
        # If the stack is empty, return None
        # (it would also be reasonable to throw an exception)
        if not self.items:
            return None

        return self.items.pop()

    def peek(self):
        """Return the last item without removing it"""
        if not self.items:
            return None
        return self.items[-1]


class MaxStack:
    def __init__(self):
        # Your code here
        self.stack = Stack()
        self.maxes_stack = Stack()

    def push(self, item):
        """Add a new item onto the top of our stack."""
        # Your code here
        self.stack.push(item)

        if self.maxes_stack.peek() is None or item >= self.maxes_stack.peek():
            self.maxes_stack.push(item)

    def pop(self):
        """Remove and return the top item from our stack."""
        # Your code here
        item = self.stack.pop()

        if item == self.maxes_stack.peek():
            self.maxes_stack.pop()

        return item

    def get_max(self):
        """The last item in maxes_stack is the max item in our stack."""
        # Your code here
        return self.maxes_stack.peek()


ms = MaxStack()
ms.push(20)
ms.push(30)
ms.push(9)
ms.push(102)
ms.push(33)
ms.push(1)
ms.pop()
ms.pop()
ms.pop()
print(ms.get_max())

"""# Optionals"""

"""
Your goal is to define a `Queue` class that uses two stacks. Your `Queue` class
should have an `enqueue()` method and a `dequeue()` method that ensures a
"first in first out" (FIFO) order.
As you write your methods, you should optimize for time on the `enqueue()` and
`dequeue()` method calls.
The Stack class that you will use has been provided to you.
"""


class Song:
    def __init__(self, name, link):
        self.name = name
        self.link = link

    def __repr__(self):
        return f"{self.name}: {self.link}"


s1 = Song("Bob The Builder", "http://www.gogle.co.uk/")
s2 = Song("Eclipse - Pink Floyd 1", "http://www.yashoo.com")
s3 = Song("Bob The Builder 2", "http://www.gogle.co.uk/")
s4 = Song("Eclipse - Pink Floyd 2", "http://www.yashoo.com")
s5 = Song("Bob The Builder 3", "http://www.gogle.co.uk/")
s6 = Song("Eclipse - Pink Floyd 3", "http://www.yashoo.com")
s7 = Song("Bob The Builder", "http://www.gogle.co.uk/")
s8 = Song("Eclipse - Pink Floyd Uncut", "http://www.yashoo.com")


class Stack:
    def __init__(self):
        self.data = []

    def push(self, item):
        self.data.append(item)

    def pop(self):
        if len(self.data) > 0:
            return self.data.pop()
        return "The stack is empty"


class QueueTwoStacks:
    def __init__(self):
        # Your code here
        self.in_stack = Stack()
        self.out_stack = Stack()

    def enqueue(self, item):
        # Your code here
        self.in_stack.push(item)

    def dequeue(self):
        # Your code here
        if len(self.out_stack.data) == 0:
            while len(self.in_stack.data) > 0:
                stack_item = self.in_stack.pop()
                self.out_stack.push(stack_item)
            if len(self.out_stack.data) == 0:
                return "can not dequeue from an empty queue"

        return self.out_stack.pop()


# q = QueueTwoStacks()
# q.enqueue(20)
# q.enqueue(220)
# q.enqueue(201)
# q.enqueue(120)
# q.enqueue(230)
# q.enqueue(320)
# q.enqueue(3)

# l3 = []
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())

q = QueueTwoStacks()
q.enqueue(s1)
q.enqueue(s2)
q.enqueue(s3)
q.enqueue(s4)
q.enqueue(s5)
q.enqueue(s6)
q.enqueue(s7)

l3 = []
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())

print(l3)

Last updated