数据结构python版(二)栈

1、线性结构Linear Structure
线性结构是一种有序数据项的集合,其中每个数据项都有唯一的前驱和后继。
不同线性结构的区别在于数据项增减的方式。
2、栈Stack
在栈里数据项的加入和移除都在同一端,也是线性结构的一种,最新加入的会被最新移除,例如盘子,一堆书等,浏览器的后退按钮,word中的撤销操作。
(1)操作方法
Stack():创建一个空栈,不包含任何数据项
push(item):将item加入栈,无返回值
pop():将栈顶数据项移除,并返回,栈被修改
peek():窥视栈顶数据项,返回栈顶的数据项但不移除
isEmpty():返回栈是否为空栈
size():返回栈中数据项个数
栈可以放各种类型的数据
(2)如何实现栈
通过class借由列表来定义
可以将List的任意一端设置为栈顶(index=0或-1)

class Stack:
    def __init(self):
        self.items=[]
    def isEmpty(self):
        return self.items ==[]
    def push(self,item):
        self.items.append(item)
    def pop(self):
        return self.items.pop()
    def peek(self):
        return self.items[len(self.items)-1]
    def size(self):
        return len(self.items)

通向也可以把列表的第一位作为栈顶,此时push/pop的复杂度为O(n),而原方法相应操作的复杂度为O(1)

class Stack:
    def __init(self):
        self.items=[]
    def isEmpty(self):
        return self.items ==[]
    def push(self,item):
        self.items.insert(0,item)
    def pop(self):
        return self.items.pop(0)
    def peek(self):
        return self.items[0]
    def size(self):
        return len(self.items)

(3)应用:简单括号匹配
目标是检测左右括号是否互相匹配
从左到右扫描括号串,打开最新的左括号应该匹配到最先遇到的右括号,这样第一个打开的左括号会匹配最后一个右括号。
代码示例

from pythonds.basic.stack import Stack
def parChecker(symbolString):
    s=Stack()
    balanced=True
    index=0
    while index < len(symbolString) and balanced:
        symbol = symbolString[index]
        if symbol =='(':
            s.push(symbol)
        else:
            if s.isEmpty():
                balanced = False
            else:
                s.pop()
        index +=1
    if balanced and s.isEmpty():
        return True
    else:
        return False
print(parChecker('((()))'))
print(parChecker('(()'))

多种括号类型匹配同理([)]也是不匹配的

from pythonds.basic.stack import Stack
def parChecker(symbolString):
    s=Stack()
    balanced=True
    index=0
    while index < len(symbolString) and balanced:
        symbol = symbolString[index]
        if symbol =='([{':
            s.push(symbol)
        else:
            if s.isEmpty():
                balanced = False
            else:
                top=s.pop()
                if not matches(top,symbol):
                   balanced=False
        index +=1
    if balanced and s.isEmpty():
        return True
    else:
        return False
def mathches(open,close):
    opens="([{"
    closers=")]}"
    return opens.index(open) == closers.index(close)
print(parChecker('((()))'))
print(parChecker('(()'))

(4)应用:十进制转换为二进制
连续除以二是得到的是从低到高的位数,但是输出是从高位到低位,需要用栈反转输出

from pythonds.basic.stack import Stack
def divideBy2(decNumber):
   remstack=Stack()
   while decNumber>0:
       rem=decNumber % 2
       remstack.push(rem)
       decNumber = decNumber //2
   binString =""
   while not remstack.isEmpty():
       binString = binString +str(remstack.pop())
   return binString
print(divideBy2(42))

十进制转换为任意进制

from pythonds.basic.stack import Stack
def divideBy2(decNumber,base):
   digits="0123456789ABCDEF"
   remstack=Stack()
   while decNumber>0:
       rem=decNumber % base
       remstack.push(rem)
       decNumber = decNumber //base
   binString =""
   while not remstack.isEmpty():
       binString = binString +digits[remstack.pop()]
   return binString
print(divideBy2(42))

(5) 表达式转换
前缀与后缀表达式:操作符相对于两个数字的位置
eg:a+bc 可以变为+abc 或abc*+
在前缀和后缀表达式中操作符的次序完全决定了运算的次序
例子
全括号的中缀表达式变成前缀或后缀
eg (bc)用代替(的位置并删去),即生成前缀表达式,相反是后缀表达式
故先把中缀表达式换为全括号形式,再进行相应的变化。
在转换过程中操作符要比操作数晚输出,古要先把操作符保存,但由于优先级规则,操作符可能要反转次序输出eg: a+bc 后缀为abc+,+在前面却要后输出,因此用栈保存。
而遇到左括号时,先标记一下,其后出现的操作符的优先级提升了,一旦扫描到对应的右括号,就可以马上输出这个操作符了。
约定中缀表达式是由空格隔开的一系列单词(token)构成,其中操作符单词包括/
-+(),而操作单词则是单字母标识符A,B,C等。
(a)先创建空栈opstack用于暂存操作符,空表postfixList用于保存后缀表达式
(b)将中缀表达式转换为单词(token)列表
eg: A+BC =split=>[‘A’,’+’,‘B’,’’,‘C’]
©从左到右扫描中缀表达式单词列表
if单词是操作数,则直接添加到后缀表达式列表的末尾
如果单词是左括号,则压入opstack栈顶
如果单词是右括号,则反复弹出opstack栈顶操作符,加入到输出列表的末尾,知道碰到左括号
如果单词是操作符*/-+,则压入opstack栈顶,这里在压入前要比较其与栈顶操作符的优先级,如果栈顶的高于或等于它,则要反复弹出栈顶操作符,加入到输出列表的末尾,直到栈顶的操作符优先级低于它。
(d)扫描结束后把opstack里剩下的依次弹出,添加到末尾。
(e)把输出列表再用join方法合并成后缀表达式字符串,算法结束。
代码如下:

from pythonds.basic.stack import Stack
def infixToPostfix(infixexpr):
#先定义操作符的优先级
    prec={}
    prec["/"]=3
    prec["*"]=3
    prec["+"]=2
    prec["-"]=2
    prec["("]=1
    opStack=Stack()
    postfixList=[]
    tokenList=infixexpr.split()
    #扫描
    for token in tokenList
    if token in "AQWERTYUIOPSDFGHJKLZXCVBNM" or token in "1234567890":
        postfixList.append(token)
    elif token =='(':
        opStack.push(token)
    elif token ==')':
        toptoken=opStack.pop()
        while topToken !='(':
            postfixList.append(topToken)
            topToken=opStack.pop()
    else:
        while (not opStack.isEmpty()) and \
            (prex[opStack.peek()] >= prec[token]):
                postfixList.append(opStack.pop())
        opStack.push(token)
    while not opStack.isEmpty():
        postfixList.append(opStack.pop())
    return "".join(postfixList)     

(6)后缀表达式求值
关键是操作符在操作数的后面,所以要先存操作数,有了操作符后再进行计算。仍然是栈的特性,操作符只作用于离它最近的两个数。这里需要注意先出栈的是右操作数,中间结果作为操作数还要继续压入栈中,最后只留一个数

from pythonds.basic.stack import Stack
def postfixEval(postfixExpr):
    opStack=Stack()
    tokenList=postfixExpr.split()
    #扫描
    for token in tokenList:
        if token in "1234567890":
            opStack.push(int(token))
        else:
            oper2=opStack.pop()
            oper1=opStack.pop()
            result=doMath(token,oper1,oper2)
            opStack.push(result)
    return opStack.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   
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构是计算机科学中非常重要的概念,它用于组织和存储数据,以便能够高效地进行操作和访问。Python提供了许多内置的数据结构,下面是一些常见的数据结构及其Python实现: 1. 列表(List):列表是Python中最常用的数据结构之一,它可以存储任意类型的元素,并且可以动态地改变大小。列表使用方括号 [] 来表示,可以通过索引访问和修改元素。 2. 元组(Tuple):元组与列表类似,但是元组是不可变的,即创建后不能修改。元组使用圆括号 () 来表示,可以通过索引访问元素。 3. 字典(Dictionary):字典是一种键值对的数据结构,可以用来存储和查找具有唯一键的值。字典使用花括号 {} 来表示,键值对之间使用冒号 : 分隔。 4. 集合(Set):集合是一种无序且不重复的数据结构,可以用来进行成员关系测试和消除重复元素。集合使用花括号 {} 来表示。 5. (Stack):是一种后进先出(LIFO)的数据结构,只能在顶进行插入和删除操作。可以使用列表来实现。 6. 队列(Queue):队列是一种先进先出(FIFO)的数据结构,只能在队尾插入元素,在队头删除元素。可以使用列表或者collections模块中的deque来实现队列。 7. 链表(Linked List):链表是一种动态数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。可以使用类来实现链表。 8. 树(Tree):树是一种非线性的数据结构,由节点和边组成,每个节点可以有多个子节点。常见的树结构包括二叉树、二叉搜索树、平衡二叉树等。 9. 图(Graph):图是一种由节点和边组成的数据结构,用于表示多对多的关系。可以使用邻接矩阵或邻接表来表示图。 以上是一些常见的数据结构及其Python实现,它们在不同的场景下有不同的应用。如果你对某个具体的数据结构或其它相关问题感兴趣,我可以为你提供更详细的解答。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值