前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Data Structures and Algorithms Basics(007):Stack-Queue

Data Structures and Algorithms Basics(007):Stack-Queue

作者头像
用户5473628
发布2019-08-08 15:04:01
2600
发布2019-08-08 15:04:01
举报
文章被收录于专栏:MiningAlgorithmsMiningAlgorithms

Stack-Queue

目录:

第一部分:创建Stack

1,使用array创建stack

2,使用linklist实现stack

第二部分:创建Queue

1,使用array创建queue

2,使用linklist创建queue

第三部分:Stack-Queue练习题

1,使用堆栈实现队列

2,使用队列实现堆栈

3,最小堆栈

4,一个数组实现两个堆栈

5,堆栈排序

6,反转字符串

7,回文(Palindrome)

8,有效括号

9,简化命令行路径

10,解码字符串

11,比赛打分

12,行星碰撞

13,查找下一个较大的元素

14,查找下一个较大的元素(2):循环数组

15, 计算温度升高需要几天

16,滑动窗口最大值

17,评估算数表达式

18,实现双端队列

第一部分:创建Stack

1,使用array创建stack

2,使用linklist实现stack

代码语言:javascript
复制
# 第一部分:创建Stack,使用到了上篇中的类LinkedList和Node
class Empty(Exception):
    pass

class Outbound(Exception):
    pass

class Node:
    def __init__ (self, value = None, next = None):
        self.value = value
        self.next = next

class LinkedList:  # 定义一个链表类
    def __init__(self):
        self.head = Node()
        self.tail = None
        self.length = 0

    def peek(self):
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        return self.head.next

    def get_first(self):
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        return self.head.next
        
    def get_last(self):
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        node = self.head
        while node.next != None:
            node = node.next
        return node
    
    def get(self, index):
        if (index < 0 or index >= self.length):
            raise Outbound( 'index is out of bound' );
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        node = self.head.next
        for i in range(index):
            node = node.next
        return node
                
    def add_first(self, value):
        node = Node(value, None)
        node.next = self.head.next
        self.head.next = node
        self.length += 1   
        
    def add_last(self, value):
        new_node = Node(value)
        node = self.head
        while node.next != None:
            node = node.next
        node.next = new_node
        self.length += 1

    def add(self, index, value):
        if (index < 0 or index > self.length):
            raise Outbound( 'index is out of bound' )
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        new_node = Node(value)
        node = self.head
        for i in range(index):
            node = node.next
        new_node.next = node.next;
        node.next = new_node;
        self.length += 1     
        
    def remove_first(self):
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        value = self.head.next
        self.head.next = self.head.next.next
        self.length -= 1
        return value    
        
    def remove_last(self):
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        node = self.head.next
        prev = self.head
        while node.next != None:
            prev = node
            node = node.next
        prev.next = None
        return node.value

    def remove(self, index):
        if (index < 0 or index >= self.length):
            raise Outbound( 'index is out of bound' );
        if not self.head.next:
            raise Empty( 'LinkedList is empty' )
        node = self.head
        for i in range(index):
            node = node.next
        result = node.next;
        node.next = node.next.next;
        self.length += 1     
        return result;      
        
    def printlist(self):
        node = self.head.next
        count = 0
        while node and count<20:
            print(node.value, end = " ")
            node = node.next
            count = count + 1
        print('')

    def size(self):
        return self.length

# 1,使用array创建stack:
class ArrayStack(object):
    def __init__ (self):
        self._data = []
        
    def __len__ (self):
        return len(self._data)
    
    def is_empty(self):
        return len(self._data) == 0
    
    # O(1)
    def push(self, e):
        self._data.append(e)
        
    # O(1)
    def top(self):
        if self.is_empty( ):
            raise ValueError( 'Stack is empty' )
        return self._data[-1]
    
    # O(1)
    def pop(self):
        if self.is_empty( ):
            raise ValueError( 'Stack is empty' )
        return self._data.pop( )  
        
    def printstack(self):
        for i in range(len(self._data)):
            print(self._data[i], end = ' ')
        print()

if __name__ == '__main__':
  mystack = ArrayStack()
  print ('size was: ', str(len(mystack)))
  mystack.push(1)
  mystack.push(2)
  mystack.push(3)
  mystack.push(4)
  mystack.push(5)
  print ('size was: ', str(len(mystack)))
  mystack.printstack()
  mystack.pop()
  mystack.pop()
  print ('size was: ', str(len(mystack)))
  mystack.printstack()
  print(mystack.top())
  mystack.pop()
  mystack.pop()
  mystack.pop()
  #mystack.pop()

# 2,使用linklist实现stack: 使用到了上篇中的类LinkedList和Node
class LinkedStack(object):
    def __init__ (self):
        self._list = LinkedList()
        
    def __len__ (self):
        return self._list.length
    
    def is_empty(self):
        return self._list.length == 0
    
    # O(1)
    def push(self, e):
        self._list.add_first(e);
        
    # O(1)
    def top(self):
        return self._list.get_first().value;
    
    # O(1)
    def pop(self):
        return self._list.remove_first().value;
        
    def printstack(self):
        self._list.printlist()

if __name__ == '__main__':
  mystack = LinkedStack()
  print ('size was: ', str(len(mystack)))
  mystack.push(1)
  mystack.push(2)
  mystack.push(3)
  mystack.push(4)
  mystack.push(5)
  print ('size was: ', str(len(mystack)))
  mystack.printstack()
  mystack.pop()
  mystack.pop()
  print ('size was: ', str(len(mystack)))
  mystack.printstack()
  print(mystack.top())
  mystack.pop()
  mystack.pop()
  mystack.pop()
  #mystack.pop()

第二部分:创建Queue

1,使用array创建queue

2,使用linklist创建queue

代码语言:javascript
复制
# 第二部分:创建Queue
# 1,使用array创建queue:
class ArrayQueue:
    DEFAULT_CAPACITY = 10
    def __init__(self):
        self._data = [None] * ArrayQueue.DEFAULT_CAPACITY
        self._size = 0
        self._front = 0
        
    def __len__(self):
        return self._size
    
    def is_empty(self):
        return self._size == 0
    
    def first(self):
        if self.is_empty( ):
            raise ValueError( 'Queue is empty' )
        return self._data[self._front]
    
    def dequeue(self):
        if self.is_empty( ):
            raise ValueError( 'Queue is empty' )
        answer = self._data[self._front]
        self._data[self._front] = None
        self._front = (self._front + 1) % len(self._data)
        self._size -= 1
        return answer
    
    def enqueue(self, e):
        if self._size == len(self._data):
            self._resize(2 * len(self._data))
        pos = (self._front + self._size) % len(self._data)
        self._data[pos] = e
        self._size += 1
        
    def resize(self, cap):
        old = self._data
        self._data = [None] * cap
        walk = self._front
        for k in range(self._size):
            self._data[k] = old[walk]
            walk = (1 + walk) % len(old)
        self._front = 0
        
    def printqueue(self):
        for i in range(self._size):
            pos = (self._front + self._size - 1 - i) % len(self._data)
            #print(str(i), ": ", str(pos))
            print(self._data[pos], end = " ")  
        print()

if __name__ == '__main__':
  myqueue = ArrayQueue()
  print ('size was: ', str(len(myqueue)))
  myqueue.enqueue(1)
  myqueue.enqueue(2)
  myqueue.enqueue(3)
  myqueue.enqueue(4)
  myqueue.enqueue(5)
  print ('size was: ', str(len(myqueue)))
  myqueue.printqueue()
  myqueue.dequeue()
  myqueue.dequeue()
  print ('size was: ', str(len(myqueue)))
  myqueue.printqueue()
  myqueue.enqueue(6)
  myqueue.enqueue(7)
  myqueue.printqueue()
  myqueue.dequeue()
  myqueue.dequeue()
  print ('size was: ', str(len(myqueue)))
  myqueue.printqueue()
  myqueue.dequeue()
  myqueue.dequeue()
  myqueue.dequeue()
  print ('size was: ', str(len(myqueue)))
  myqueue.printqueue()
  #myqueue.dequeue()

# 2,使用linklist创建queue: 使用到了上篇中的类LinkedList和Node
class LinkedQueue(object):
    def __init__(self):
        self.head = None
        self.tail = None
        self.count = 0  
        
    def enqueue(self, value):
        new_node = Node(value)

        if self.tail is not None:
            self.tail.next = new_node

        else:
            self.head = new_node

        self.tail = new_node
        self.count += 1

    def dequeue(self):
        if not self.is_empty():
            # point head to next node
            tmp = self.head
            self.head = self.head.next
            print("dequeue sucess")
            self.count -= 1
            return tmp
        else:
            raise ValueError("Empty QUEUE")

    def is_empty(self):
        if self.head is None and self.tail is None:
            return True
        else:
            return False

    def peek(self):
        return self.head.data

        
    def __len__(self):
        return self.count    

    def is_empty(self):
        return self.count == 0
    
    def print(self):
        node = self.head
        while node:
            print(node.value, end = " ")
            node = node.next
        print('')

第三部分:Stack-Queue练习题

1,使用堆栈实现队列

2,使用队列实现堆栈

3,最小堆栈

4,一个数组实现两个堆栈

5,堆栈排序

6,反转字符串

7,回文(Palindrome)

8,有效括号

9,简化命令行路径

10,解码字符串

11,比赛打分

12,行星碰撞

13,查找下一个较大的元素

14,查找下一个较大的元素(2):循环数组

15, 计算温度升高需要几天

16,滑动窗口最大值

17,评估算数表达式

18,实现双端队列

代码语言:javascript
复制
# 第三部分:Stack-Queue练习题
# 1,使用堆栈实现队列:
class QueueWithTwoStacks:    
    def __init__(self):
        self.insertStack = []
        self.popStack = []

    def enqueue(self, e):
        self.insertStack.append(e)
        return e
    
    def dequeue(self):
        if len(self.insertStack)==0 and len(self.popStack)==0:
            return None        
        if len(self.popStack)==0:
            while len(self.insertStack)!=0:
                self.popStack.append(self.insertStack.pop())        
        return self.popStack.pop()

if __name__ == '__main__':
  mystack = QueueWithTwoStacks()
  e = mystack.enqueue(3)
  print(e)
  e = mystack.enqueue(2)
  print(e)
  e = mystack.enqueue(1)
  print(e)
  e = mystack.dequeue()
  print(e)
  e = mystack.dequeue()
  print(e)

# 2,使用队列实现堆栈:
class StackWithQueue:    
    def __init__(self):
        self.queue = LinkedList()

    # Push element x onto stack.
    def push(self, x):
        self.queue.add_last(x)

    # Removes the element on top of the stack.
    def pop(self):
        size = self.queue.size()
        for i in range(1, size):
            self.queue.add_last(self.queue.remove_first())
        self.queue.remove_first()
        
    def top(self):
        size = self.queue.size()
        for i in range(1, size):
            self.queue.add_last(self.queue.remove_first())
        result = self.queue.remove_first()
        self.queue.add_last(result)
        return result

if __name__ == '__main__':
  stack = StackWithQueue() 
  stack.push(1)
  stack.push(2)
  print(stack.top())

  stack = StackWithQueue()
  stack.push(1)
  stack.push(2)
  stack.pop()
  stack.push(3)
  print(stack.top())

# 3,最小堆栈:
import sys

class NodeWithMin:
    def __init__(self, v, min):
        self._value = v
        self._min = min

class MinStack1(ArrayStack):    
    def __init__(self):
        super(MinStack, self).__init__()
    
    def push(self, v):       
        newMin = min(v, self.min())
        super(MinStack, self).push(NodeWithMin(v, newMin))
    
    def min(self):
        if (super(MinStack, self).is_empty()):
            return sys.maxsize
        else:
            return super(MinStack, self).top()._min;
    
class MinStack2(ArrayStack):
    
    def __init__(self):
        super(MinStack2, self).__init__()
        self.min_stack = ArrayStack()
        
    def push(self, value):
        if value <= self.min():
            self.min_stack.push(value)
        super(MinStack2, self).push(value)
        return value
          
    def min(self):
        if self.min_stack.is_empty():
            return sys.maxsize
        else:
            return self.min_stack.top()    
      
    def pop(self):
        value = super(MinStack2, self).pop()
        if value == self.min():
            self.min_stack.pop()
        return value

if __name__ == '__main__':
  minStack = MinStack2()
  minStack.push(4)
  minStack.push(6)
  minStack.push(8)
  minStack.push(3)
  print(minStack.min())
  minStack.pop()
  minStack.pop()
  print(minStack.min())

# 4,一个数组实现两个堆栈:
class twoStacks:
     
    def __init__(self, n): 
        self.size = n
        self.arr = [None] * n
        self.top1 = -1
        self.top2 = self.size
         
    # Method to push an element x to stack1
    def push1(self, x):
         
        # There is at least one empty space for new element
        if self.top1 < self.top2 - 1 :
            self.top1 = self.top1 + 1
            self.arr[self.top1] = x
 
        else:
            print("Stack Overflow ")
 
    # Method to push an element x to stack2
    def push2(self, x):
 
        # There is at least one empty space for new element
        if self.top1 < self.top2 - 1:
            self.top2 = self.top2 - 1
            self.arr[self.top2] = x
 
        else :
           print("Stack Overflow ")
 
    # Method to pop an element from first stack
    def pop1(self):
        if self.top1 >= 0:
            x = self.arr[self.top1]
            self.top1 = self.top1 -1
            return x
        else:
            print("Stack Underflow ")
 
    # Method to pop an element from second stack
    def pop2(self):
        if self.top2 < self.size:
            x = self.arr[self.top2]
            self.top2 = self.top2 + 1
            return x
        else:
            print("Stack Underflow ")

# 5,堆栈排序:
def sortStack(s):
    r = ArrayStack()    
    while not s.is_empty():
        tmp = s.pop()       
        while not r.is_empty() and r.top() > tmp:
            s.push(r.pop())            
        r.push(tmp)    
    return r

def sortedInsert(s, x):
    if len(s) == 0 or x > s.top():
        s.push(x)
        return
    temp = s.pop()
    sortedInsert(s, x)
    s.push(temp)
    
def sortStack(s):
    if len(s) != 0:
        x = s.pop()
        sortStack(s)
        sortedInsert(s, x)

if __name__ == '__main__':
  s = ArrayStack()
  s.push(30)
  s.push(-5)
  s.push(18)
  s.push(14)
  s.push(-3)
  s.printstack()
  sortStack(s)
  s.printstack()

# 6,反转字符串:
def reverse(s):
    lst = []
    for i in s:
        lst.append(i)
    result = []
    while len(lst) != 0:
        result.append(lst.pop())
    return ''.join(result)

if __name__ == '__main__':
  s = "hello world"
  print(reverse(s))

# 7,回文(Palindrome):
def isPalindrome(s):
    r = reverse(s)
    return r == s

if __name__ == '__main__':
  s = "hello world"
  print(reverse(s))

# 8,有效括号:
def isValid(s):
    stack = []
    for c in s:
        if (c == '(' or c == '[' or c == '{'):
            stack.append(c)
        else:
            if len(stack)==0:
                return False
            if (   (c == ')' and stack[-1] == '(')
                or (c == ']' and stack[-1] == '[')
                or (c == '}' and stack[-1] == '{')):
                stack.pop()
            else:
                return False
    return len(stack)==0

if __name__ == '__main__':
  s = "{{{}}{}{{}}}"
  print(isValid(s))

# 9,简化命令行路径:
def simplifyPath(path):
    lst = []
    splits = path.split("/")
    
    for s in splits:
        if s == "":
            continue
        if s == ".":
            continue
            
        if s == "..":
            if len(lst) != 0:
                lst.pop()
        else:
            lst.append(s)
    
    result = []
    if len(lst) == 0:
        return "/"
    result = ['/' + i for i in lst]
    return ''.join(result)
    
if __name__ == '__main__':
  path = "/home/"
  print(simplifyPath(path))

# 10,解码字符串:
def decodeString(s):
    stack = []
    stack.append(["", 1])
    num = ""
    for ch in s:
        if ch.isdigit():
            num += ch
        elif ch == '[':
            stack.append(["", int(num)])
            num = ""
        elif ch == ']':
            st, k = stack.pop()
            stack[-1][0] += st*k
        else:
            stack[-1][0] += ch
    return stack[0][0]

if __name__ == '__main__':
  s = "2[abc]3[cd]ef"
  print(decodeString(s))

# 11,比赛打分:
def calPoints(ops):
    stack = []
    for op in ops:
        if op == '+':
            stack.append(stack[-1] + stack[-2])
        elif op == 'C':
            stack.pop()
        elif op == 'D':
            stack.append(2 * stack[-1])
        else:
            stack.append(int(op))

    return sum(stack)

if __name__ == '__main__':
  ops = ["5","-2","4","C","D","9","+","+"]
  print(calPoints(ops))

# 12,行星碰撞:
def asteroidCollision(asteroids):
    ans = []
    for new in asteroids:
        while ans and new < 0 < ans[-1]:
            if ans[-1] < -new:
                ans.pop()
                continue
            elif ans[-1] == -new:
                ans.pop()
            break
        else:
            ans.append(new)
    return ans

if __name__ == '__main__':
  asteroids = [10, 2, -5] 
  print(asteroidCollision(asteroids))

# 13,查找下一个较大的元素:没有比当前值大的元素则返回0
def nextGreat(nums):
    if len(nums) == 0:
        return
    stack = []
    stack.append(nums[0])    
    for i in range(1, len(nums)):
        while (len(stack) != 0 and nums[i] > stack[-1]):
            num = stack.pop()
            print(num, ": ", array[i])
        stack.append(nums[i])        
    while len(stack) != 0:
        print(stack.pop(), ": -1")
if __name__ == '__main__':
  array = [6, 4, 5, 2, 25]
  nextGreat(array)

# 14,查找下一个较大的元素:与上面不同的是,这里是循环数组
def nextGreat2(nums):
    stack, r = [], [-1] * len(nums)
    for i in range(len(nums)):
        while stack and (nums[stack[-1]] < nums[i]):
            r[stack.pop()] = nums[i]
        stack.append(i)
    print(r)
    for i in range(len(nums)):
        while stack and (nums[stack[-1]] < nums[i]):
            r[stack.pop()] = nums[i]
        if stack == []:
            break
    return r

if __name__ == '__main__':
  array = [37, 6, 4, 5, 2, 25]
  nextGreat2(array)

# 15,日常温度:根据日常气温列表,制作一个列表,在输入的每一天中,都会告诉您需要等待多长时间,直到温度升高.如果没有可能的将来的日子,返回0
def dailyTemperatures(temperatures):
    if not temperatures: return []
    result, stack = [0] * len(temperatures), []
    stack.append((temperatures[0], 0))

    for i in range(1, len(temperatures)):
        while stack:
            prev = stack[-1]
            if prev[0] < temperatures[i]:
                result[prev[1]] = i - prev[1]
                stack.pop()
            else:
                break
        stack.append((temperatures[i], i))
    return result

def dailyTemperatures2(temperatures):
    if not temperatures: return []
    result, stack = [0] * len(temperatures), []
    stack.append(0)

    for i in range(1, len(temperatures)):
        while stack:
            prev = stack[-1]
            if temperatures[prev] < temperatures[i]:
                result[prev] = i - prev
                stack.pop()
            else:
                break
        stack.append(i)
    return result

if __name__ == '__main__':
  t = [73, 74, 75, 71, 69, 72, 76, 73]
  print(dailyTemperatures(t))

# 16,滑动窗口最大值:
from collections import deque

def movingMax(arr,k):
    n = len(arr)
    Qi = deque()
    
    # Process first k (or first window) 
    # elements of array
    for i in range(k):
        # For every element, the previous 
        # smaller elements are useless
        # so remove them from Qi
        while Qi and arr[i] >= arr[Qi[-1]] :
            Qi.pop()
        
        # Add new element at rear of queue
        Qi.append(i);
        
    # Process rest of the elements, i.e. 
    # from arr[k] to arr[n-1]
    for i in range(k, n):
        
        # The element at the front of the
        # queue is the largest element of
        # previous window, so print it
        print(str(arr[Qi[0]]) + " ", end = "")
        
        # Remove the elements which are 
        # out of this window
        while Qi and Qi[0] <= i-k:
            
            # remove from front of deque
            Qi.popleft() 
        
        # Remove all elements smaller than
        # the currently being added element 
        # (Remove useless elements)
        while Qi and arr[i] >= arr[Qi[-1]] :
            Qi.pop()
        
        # Add current element at the rear of Qi
        Qi.append(i)
    
    # Print the maximum element of last window
    print(str(arr[Qi[0]]))

if __name__ == '__main__':
  arr = [12, 1, 78, 90, 57, 89, 56]
  k = 3
  movingMax(arr, k)

# 17,评估算数表达式:
def infixToPostfix(infixexpr):
    prec = {}
    prec["*"] = 3
    prec["/"] = 3
    prec["+"] = 2
    prec["-"] = 2
    prec["("] = 1
    opStack = []
    postfixList = []
    tokenList = infixexpr.split()

    for token in tokenList:
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfixList.append(token)
        elif token == '(':
            opStack.append(token)
        elif token == ')':
            topToken = opStack.pop()
            while topToken != '(':
                postfixList.append(topToken)
                topToken = opStack.pop()
        else:
            while (len(opStack) != 0) and \
               (prec[opStack[-1]] >= prec[token]):
                postfixList.append(opStack.pop())
            opStack.append(token)

    while len(opStack) != 0:
        postfixList.append(opStack.pop())
    return " ".join(postfixList)

def postfixEval(postfixExpr):
    operandStack = []
    tokenList = postfixExpr.split()

    for token in tokenList:
        if token in "0123456789":
            operandStack.append(int(token))
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            result = doMath(token, operand1, operand2)
            operandStack.append(result)
    return operandStack.pop()

def doMath(op, op1, op2):
    if op == "*":
        return op1 * op2
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    else:
        return op1 - op2

if __name__ == '__main__':
  print(infixToPostfix("A * B + C * D"))
  print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )"))
  print(infixToPostfix("A + B * C - ( D - E ) * F + G"))

  print(postfixEval('1 2 + 3 * 4 5 - 6 7 + * -'))
  print(postfixEval('1 2 3 * + 4 5 - 6 * - 7 +'))


# 18,双端队列:允许在两端插入和删除
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MiningAlgorithms 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档