美文网首页
stack/queue, since 2020-04-18

stack/queue, since 2020-04-18

作者: Mc杰夫 | 来源:发表于2020-04-18 12:08 被阅读0次

    (2020.04.18)
    *注: 除了本文中提到的list表达,还可以用linked list实现stack/queue。

    Stack

    Stack: Last In First Out (LIFO)
    Stack的array-based实现方法:
    直接用Python的list实现。注意到stack.push()可用list.append()实现,而stack.pop()可用list.pop()实现。这种一种类的方法实为对另一种类的方法的调用,称为设计模式中的适配器模式 (adapter pattern)

    class Empty(Exception):
        pass
    
    class array_stack:
        def __init__(self):
            self._data = []
        def __len__(self):
            return len(self._data)
    
        def is_empty(self):
            return len(self._data) == 0
    
        def push(self, p):
            return self._data.append(p)
    
        def pop(self):
            if self.is_empty():
                raise Empty('Stack empty')
            return self._data.pop()
    
        def top(self):
            return self._data[-1]
    

    复杂度分析:
    考虑到该方法的base是Python list,所以操作可以参考list对应的操作。
    stack.push(p): O(1) amortised
    stack.pop(): O(1) amortised
    stack.is_empty(): O(1)
    stack.top(): O(1)
    stack._ _ len _ _(): O(1)
    提速方法:
    初始化过程中将hidden list从长度0改为长度n (用户定义),这种方式比从长度0开始的list更高效 (但复杂度保持不变?)。
    应用: reverse a sequence反转,matching parentheses and HTML tags检查括号匹配。
    括号匹配的算法和实例:
    对序列做扫描从左到右,每次遇到左括号(open symbol),push it into stack。每次遇到右括号(close symbol),pop a symbol from the stack(非空),并检测popped symbol和右括号是否是valid pair。如果完成扫描并且均是匹配,则该序列的括号合理匹配。

    def is_match(seq):
        lefty, righty = '([{', ')]}'
        s = array_stack()
        for oc in seq:
            if oc in lefty:
                s.push(oc)
            elif oc in righty:
                if s.is_empty(): 
                    return False
                if righty.index(oc) != lefty.index(s.pop()):
                    return False
        return s.is_empty()
    

    Queue

    Queue: First In First Out (FIFO)
    操作: queue.enqueue(p)从尾部加入p, queue.dequeue()剔除头部点。
    Queue的低效实现方法:

    • 直接用list实现,queue.push(a)参考list.append(a),queue.pop()参考list.pop(0)。.push复杂度O(1) amortised,.pop复杂度是O(n),其中n表示list长度,因为list.pop(0)在删除了index=0元素后便将从index=1开始到结尾平移到index=0开始。
    • 与前一种方法相似,queue.push(a)相同,但queue.pop()的方法不同于list.pop(0)。queue.pop()时queue的头部元素变成None,同时head index加1。这种方法的特点是push次数越多,list长度越长,pop次数越多list头部的None越多。

    一种高效的实现方式: using an array Circularly
    一个list,有头、尾两个指针,记录头、尾的位置,初始为0、0。每次push操作尾index+1,每次pop操作头index+1,前提是index+1之后的指针值没超过list长度。或者不设置尾指针,而有头指针结合queue length计算尾指针。如果超过list长度,则执行求模module操作,tail = (tail+1) % len(list),这种操作可以保证在index=9之后+1操作回到index=0的职位,成为一个circule。每次push操作后queue length += 1,每次pop操作后queue length -= 1。

    class circular_array_queue:
        DEFAULT_CAPACITY = 20
        def __init__(self):
            self._data = [None] * circular_array_queue.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 Empty('Queue empty')
            return self._data[self._front]
        def dequeue(self):
            if self.is_empty():
                raise Empty('Queue empty')
            answer = self._data[self._front]
            self._data[self._front] = None
            self._front = (self._front + 1) % len(self._data) 
            # len(self._data) not exactly circular_array_queue.DEFAULT_CAPACITY, 
            # which depends on whether the queue is resized or not
            self._size -= 1
            return answer
        def enqueue(self, e):
            if self._size == len(self._data):
                self._resize(2*len(self._data))
            tail = (self._front + self._size) % len(self._data)
            self._data[tail] = e
            self._size += 1
        def _resize(self, newlen):
            old = self._data
            self._data = [None] * newlen
            walk = self._front
            for k in range(self._size):
                self._data[k] = old[walk]
                walk = (walk+1) % len(old)
            self._front = 0
    

    复杂度分析:
    queue.enqueue(n): O(1) amortised
    queue.dequeue(): O(1) amortised
    queue.first(): O(1)
    queue.is_empty(): O(1)
    queue.is_empty(): O(1)
    queue.len(): O(1)

    reference:

    1. M.T. Goodrich and etc., Data Structures and Algorithms.

    相关文章

      网友评论

          本文标题:stack/queue, since 2020-04-18

          本文链接:https://www.haomeiwen.com/subject/ludvvhtx.html