数据结构[Python--Stack]

发布时间:2019-09-11 07:42:51编辑:auto阅读(1598)

    难得有些许空闲,看一下Python的数据结构--Stack,现将几个典型示例进行总结!

    一、什么是栈

         栈是一个有序集合,根据其特性可以称为"先进后出"或"后进先出", 其中添加或删除都发生在同一端,这一端被称为"栈顶",与其对应的叫"栈底"。

        栈的底部很重要,因为其底部存储的数据是时间最长的,最近的添加项总是最先会弹出,这种排序原则有时被称为"LIFO"

    二、栈

    1. 栈的可用操作

    • Stack() 创建一个空的新栈。 它不需要参数,并返回一个空栈。

    • push(item)将一个新项添加到栈的顶部。它需要 item 做参数并不返回任何内容。

    • pop() 从栈中删除顶部项。它不需要参数并返回item 。栈被修改。

    • top() 从栈返回顶部项,但不会删除它。不需要参数。 不修改栈。

    • isEmpty()测试栈是否为空。不需要参数,并返回布尔值。

    • size() 返回栈中的item 数量。不需要参数,并返回一个整数。

    • clear 清空栈,没有返回值

    2. 利用Python 的内置的数据结构List实现栈全部操作

    class Stack():
        def __init__(self):
            self.itmes = []
        def isEmpty(self):
            return self.itmes == []
        def clear(self):
            del self.itmes[:]
        def push(self, item):
            self.items.append(item)
        def pop(self):
            return self.itmes.pop()
        def top(self):
            return self.items[-1]
        def size(self):
            return len(self.itmes)

    3. 栈的使用示例

    3.1 进制转换

    class Stack():
        def __init__(self):
            self.itmes = []
        def isEmpty(self):
            return self.itmes == []
        def clear(self):
            del self.itmes[:]
        def push(self, item):
            self.items.append(item)
        def pop(self):
            return self.itmes.pop()
        def top(self):
            return self.items[-1]
        def size(self):
            return len(self.itmes)
    def divideBy2(decNumber, base):
        remstack = Stack()
        while decNumber > 0:
            rem = decNumber % base
            remstack.push(rem)
            decNumber = decNumber // base
        binString = ""
        while not remstack.empty():
            binString = binString + str(remstack.pop())
        return binString
    if __name__ == '__main__':
        print(divideBy2(42, 2))

    说明: 这是用List结构来实现的"栈", 同样我们可以自己写一个栈

    3.2 自己写栈

    class Node:
        def __init__(self, value):
            self.value = value
            self.next = None
    class Stack:
        def __init__(self):
            self.top = None
        def push(self, value):
            node = Node(value)
            node.next = self.top
            self.top = node
        def pop(self):
            node = self.top
            self.top = node.next
            return node.value
    s = Stack()
    s.push(3)
    s.push('ac')
    s.push('er')
    s.pop()
    s.push(5)

    说明

    1. 上面所定义的栈,是由top指针指向一个完整的Node实例

    2. 定义一个栈,使用指针控制其读取的位置。

    3.3 栈应用--前缀表达式(波兰式)

    from __future__ import division
    class Node():
        def __init__(self, value):
            self.value = value
            self.next = None
    class StackNode():
        def __init__(self):
            self.top = None
        def push(self, value):
            node = Node(value)
            node.next = self.top
            self.top = node
        def pop(self):
            node = self.top
            self.top = node.next
            return node.value
    def compute_exec(op, ov1, ov2):
        def add(ov1, ov2):
            return ov1 + ov2
        def sub(ov1, ov2):
            return ov1 - ov2
        def mul(ov1, ov2):
            return ov1 * ov2
        def div(ov1, ov2):
            return ov1 / ov2
        ops = {add: '+', sub: '-', mul: '*', div: "/"}
        for k, v in ops.items():
            if v == op:
                ret = k(ov1, ov2)
                stack1.push(ret)
                break
    def perfix_reverse(string):  # reverse
        tmp = ''
        for s in string[::-1]:
            if s == "(":
                tmp += ")"
            elif s == ")":
                tmp += "("
            else:
                tmp += s
        return tmp
    def infix_to_prefix(string):
        opt = ''
        string_tmp = perfix_reverse(string)
        for i in string_tmp:  #  前缀表达式
            if i.isdigit():
                opt = i + opt
            elif i != ')':
                stack1.push(i)
            elif i == ")":
                opt = stack1.pop() + opt
                stack1.pop()
        for s in opt[::-1]:
            if s.isdigit():
                stack1.push(s)
            else:
                    op1 = s
                    ov1 = stack1.pop()
                    ov2 = stack1.pop()
                    compute_exec(op1, int(ov1), int(ov2))  # compute result 
                    continue
        return opt, stack1.pop()
    if __name__ == '__main__':
        stack1 = StackNode()  # 操作符
        infix = ['((3+4)*2)', '((3+(4*2))-1)', '(5*(1+2))']
        for i, v in enumerate(infix):
            print infix[i], "==>", infix_to_prefix(v)

    说明:

    1. 前缀表达式就是说操作符位于操作数之前

    2. 表达式从右向左依次解析。将数值压栈,遇到符号将栈顶的操作数与次位置弹出进行计算,结果再次入栈,直到表达式解析完成。

    3.4 栈应用--后缀表达式(逆波兰式)

    class Node():
        def __init__(self, value):
            self.value = value
            self.next = None
    class StackNode():
        def __init__(self):
            self.top = None
        def push(self, value):
            node = Node(value)
            node.next = self.top
            self.top = node
        def pop(self):
            node = self.top
            self.top = node.next
            return node.value
    def compute_exec(op, ov1, ov2):
        def add(ov1, ov2):
            return ov1 + ov2
        def sub(ov1, ov2):
            return ov1 - ov2
        def mul(ov1, ov2):
            return ov1 * ov2
        def div(ov1, ov2):
            return ov1 / ov2
        ops = {add: '+', sub: '-', mul: '*', div: "/"}
        for k, v in ops.items():
            if v == op:
                ret = k(ov1, ov2)
                stack1.push(ret)
                break
    def postfix(expr):
        for s in expr:
            if s.isdigit():
                stack2.push(s)
            elif s != ")":
                stack1.push(s)
            elif s == ")":
                top = stack2.pop()
                snext = stack2.pop()
                stack2.push(''.join([snext, top, stack1.pop()]))
                stack1.pop()
        post_expr = stack2.pop()
        for i in post_expr:
            if i.isdigit():
                stack1.push(i)
            else:
                op = i
                top = stack1.pop()
                snext = stack1.pop()
                compute_exec(op, int(snext), int(top))
        return post_expr, stack1.pop()
    if __name__ == '__main__':
        stack1 = StackNode()  # 操作符
        stack2 = StackNode()  # 操作数
        exprs = ['((3+(4*2))-1)', '((3*4)+(3/2))']
        for e in exprs:
            print e, "==>", postfix(e)

    说明:

    1.  后缀表达式就是说操作符位于操作数之后。

    2.  表达式从左向右依次解析。将数值压栈,遇到符号将栈顶的操作数与次位置弹出进行计算[次位操作数 栈顶操作数 操作符 ],结果再次入栈,直到表达式解析完成

    3.  计算表达式结果时同样是[次位操作数 操作符 栈顶操作数 ]


    四、总结

    1. 以上示例都可以通过http://pythontutor.com/visualize.html#mode=edit 查看程序运行的每一步

    2. 本文参考于https://www.gitbook.com/book/facert/python-data-structure-cn/details

    3. 以上后两个示例代码基于自己理解所写,可能存在bug

    4. 后两个示例的缺点是没有写表达式合法性的检查,表达式的优先级(如表达式无括号可能会导致程序异常)

    5. 此处仅是对栈的一此粗浅理解及应用。


关键字