def run_stack_demo(): print("\nRandomly generated stack") stack = Stack() for i in range(10): stack.push_random_number() popped = 1 while popped: popped = stack.pop() print(f"Popped {popped}")
def valid_parenthesis(s: str) -> bool: """ Returns whether the parenthetical expression, s, is valid. @Algorithm: - Keep track of open parens that require terminating using a stack - If we encounter an open paren, push to indicate we are still to find a terminating closed paren - If we encounter a closed paren, - If open paren stack is empty, then we cannot match the closed paren to anything -- invalid - Check if closed paren terminates the open paren at the top of the stack - If it does, pop() the open paren to indicate we have found its termination - If it doesn't, then -- invalid :param s: string with parentheses :Time: O(N) :Space: O(N) :return: true if valid """ open_parens = Stack( ) # tracks history of open parentheses that need to be terminated for c in s: if c in closed_parens: # if closed paren, check if top of stack is open paren of same type if open_parens.get_size() == 0: return False # no open paren to match this closed paren if open_parens.peek() == matching_open_paren[ c]: # proper termination found for open paren at top of stack open_parens.pop( ) # pop to indicate this paren has found a terminating closing paren else: return False # incorrect termination else: open_parens.push(c) # if open paren, add to stack return open_parens.is_empty( ) # if stack is empty, valid; else, indicates an open paren hasn't been terminated
def depth_first_search(start, goals=[]): stack = Stack((start, start.previous)) visited = {start.id: True} while len(stack) > 0: node, previous = stack.pop() if node.id in goals: return node for neighbor, cost in node.expand_neighbors(): if neighbor.id not in visited: visited[neighbor.id] = True neighbor.previous = node stack.push((neighbor, node)) return None
class StackWithMin(Stack): def __init__(self): super(StackWithMin, self).__init__() self.s2 = Stack( ) # This stack stores the minimum element; the top of the stack contains the minimum def push(self, item): # This time, when pushing, we check to see if the item being pushed is less than (or equal) to our current min # If so, we add this item to the top of our second stack if item <= self.get_min(): self.s2.push(item) super().push(item) def pop(self): ret_val = super().pop() # This time, when popping, if the item we are popping is the minimum, reflect this in our second stack, s2 if ret_val == self.get_min(): self.s2.pop() return ret_val def get_min(self): """ Returns the minimum element in the original stack, which is stored at the top of s2. :Time: O(1) :Space: O(1) :return: the minimum element in the stack """ if self.s2.is_empty(): return float('+inf') else: return self.s2.peek()
def is_palindrome(head: ListNode) -> bool: """ Returns whether the linked list is a palindrome. Algorithm: Add each node into a stack Then, for each node pop() and check if that node equals the popped node; if not, return False since a palindrome must read the same backwards and forwards :param head: head of list :Time: O(N) :Space: O(N) :return: true if palindrome """ S = Stack() curr = head while curr is not None: S.push(curr) # add each node onto a stack curr = curr.next curr = head while curr is not None: if curr.key != S.pop( ).key: # check if the current node is the same as the node at the top of the stack return False # if not, then LL is not a palindrome curr = curr.next return True
def sort_stack(s1): ''' sorts a stack with smallest elements on top ''' if s1.is_empty(): return False s2 = Stack() s2.push(s1.pop()) while not s1.is_empty(): compare(s1, s2) while not s2.is_empty(): s1.push(s2.pop())
def clone_reverse(head: ListNode) -> ListNode: """ Reverses the original list by creating a new one with the help of a stack :param head: original list head :Time: O(N) :Space: O(N) :return: new list head """ S = Stack() curr = head while curr is not None: S.push(curr) # add each node onto a stack curr = curr.next new_list = ListNode(S.pop().key) new_list_head = new_list while not S.is_empty(): new_list.next = ListNode(S.pop().key) new_list = new_list.next return new_list_head
"""Exercise 10.1-1.""" # Using Figure 10.1 as a model, illustrate the result of each operation in the # sequence PUSH(S,4), PUSH(S,1), PUSH(S,3), POP(S), PUSH(S,8), and POP(S) on # an initially empty stack S stored in array S[1...6]. from data_structures.Stack import Stack if __name__ == "__main__": S = Stack() print(S.items) S.push(4) print(S.items) S.push(1) print(S.items) S.push(3) print(S.items) S.pop() print(S.items) S.push(8) print(S.items) S.pop() print(S.items)
def __init__(self): super(MyQueue, self).__init__() self.s1 = Stack() self.s2 = Stack()
class MyQueue(Queue): def __init__(self): super(MyQueue, self).__init__() self.s1 = Stack() self.s2 = Stack() def enqueue(self, item): """ Enqueues an item onto the queue by pushing the item onto stack 1. :param item: item to enqueue :Time: O(1) :Space: O(1) :return: none """ self.s1.push(item) # Simply push item onto s1 def dequeue(self): """ Returns the element at the front of the queue. This is achieved by popping from s2, which mimics a queue. @note: To save needlessly shifting elements into s2, we will only populate s2 when it is depleted. I.e. only update s2 until the previously populated items have been popped. :Time: O(N) :Space: O(N) :return: none """ if self.s2.is_empty( ): # We will only update s2 when it cannot be popped() from further self.shift_stacks() return self.s2.pop() def peek(self): if self.s2.is_empty(): self.shift_stacks() return self.s2.peek() def shift_stacks(self): """ Pops each element in s1 and pushes it onto s2 such that s2 now mimics a queue which can be dequeued via popping :Time: O(N) :Space: O(N) :return: none """ while not self.s1.is_empty(): # pop() from s1 and push() onto s2 self.s2.push(self.s1.pop()) def get_size(self): return self.s1.get_size() + self.s2.get_size( ) # Size of queue is the size of both stacks def is_empty(self): return self.get_size() == 0
def approach_2(self, l1: ListNode, l2: ListNode) -> ListNode: """ Adds the two lists in forward order and returns the head of the resulting list. Algorithm: Insert both lists, l1 and l2, into separate stacks, S1 and S2. - Then, as from the original alg, pop off S1 and S2 concurrently and add into a new list l3 - If either S1 or S2 has remaining items, accumulate into l3 - If carry = 1, as before, we add append the carry onto the end as well. TODO: *Note that l3 is in reverse order which we do not want. E.g. 7 + 999 = 6001. Fix this by appending to start of l3. todo: hack used by reversing l3 at the end -- implement an "insertAtBeginning()" method for l3 to fix!! :param l1: list 1 :param l2: list 2 :Time: O(n + m) :Space: O(n + m) :return: head of resulting list """ # Push each list onto a separate stack S1 = Stack() S2 = Stack() while l1: S1.push(l1.key) l1 = l1.next while l2: S2.push(l2.key) l2 = l2.next # What follows is similar to the original approach l3_h = l3 = ListNode(-1) carry = 0 while not S1.is_empty() and not S2.is_empty( ): # add elements while both stacks are not empty num = S1.pop() + S2.pop() + carry l3.next = ListNode(num % 10) # add last digit of sum if num > 9: carry = 1 else: carry = 0 l3 = l3.next while not S1.is_empty(): # add remaining elements in S1 num = S1.pop() + carry l3.next = ListNode(num % 10) # add last digit of sum if num > 9: carry = 1 else: carry = 0 l3 = l3.next while not S2.is_empty(): # add remaining elements in S2 num = S2.pop() + carry l3.next = ListNode(num % 10) # add last digit of sum if num > 9: carry = 1 else: carry = 0 l3 = l3.next # important: if carry is set to 1, then it means the sum is overflowing and must include the carry bit if carry == 1: l3.next = ListNode(carry) return reverse_list( l3_h.next ) # todo this is a hack!! when appending sums, append to l3 at the beginning!!!
def __init__(self, threshold): self.threshold = threshold self.data = {1: Stack()} self.cur = 1 #current stack
def __init__(self): ''' add: push everything to s1 first ''' ''' remove: push everything to self.s2 first ''' self.s1 = Stack() self.s2 = Stack()
class My_Queue: ''' implementation of a queue using 2 stacks ''' def __init__(self): ''' add: push everything to s1 first ''' ''' remove: push everything to self.s2 first ''' self.s1 = Stack() self.s2 = Stack() def __str__(self): return "s1:\n" + str(self.s1) + "\ns2:\n" + str(self.s2) def add(self, value): while not self.s2.is_empty(): self.s1.push(self.s2.pop()) self.s1.push(value) def remove(self): while not self.s1.is_empty(): self.s2.push(self.s1.pop()) self.s2.pop() def is_empty(self): return self.s1.data == [] and self.s2.data == [] def size(self): return len(self.s1.data) + len(self.s2.data)
def runStack(): s=Stack() print(s.isEmpty()) s.push(4) s.push('dog') print(s.peek()) s.push(True) print(s.size()) print(s.isEmpty()) s.push(8.4) print(s.pop()) print(s.pop()) print(s.size())
def runStack(): s = Stack() print(s.isEmpty()) s.push(4) s.push('dog') print(s.peek()) s.push(True) print(s.size()) print(s.isEmpty()) s.push(8.4) print(s.pop()) print(s.pop()) print(s.size())
def __init__(self): super(StackWithMin, self).__init__() self.s2 = Stack( ) # This stack stores the minimum element; the top of the stack contains the minimum
return False s2 = Stack() s2.push(s1.pop()) while not s1.is_empty(): compare(s1, s2) while not s2.is_empty(): s1.push(s2.pop()) if __name__ == "__main__": print "-------Test 1----------" print "unsorted stack test" s = Stack() s.push(4) s.push(1) s.push(1) s.push(2) s.push(3) s.push(5) s.push(1) print "INITIAL:" print s sort_stack(s) print "FINAL:" print s print "-------Test 2----------" print "already sorted stack test"
def evaluate_expression(expr): values = Stack() operators = Stack() for idx, element in enumerate(expr): if element == '(': pass elif element in ['^', '+', '-', '*', '/']: operators.push(element) elif element.isdigit(): values.push(int(element)) elif element == ')': if operators.get_size() == 0: continue operand = operators.pop() values = calculate(operand, values) else: raise InvalidInputError(idx=idx, element=element) while operators.get_size() != 0: operand = operators.pop() values = calculate(operand, values) assert values.get_size( ) == 1, "Values stack contains {} elements at termination".format( values.get_size()) return float(values.pop())
def push(self, item): if self.is_full(self.data[self.cur]): self.cur += 1 if self.cur not in self.data: self.data[self.cur] = Stack() self.data[self.cur].push(item)