python数据结构 栈的应用——符号匹配,进制转化,后缀。

来源:互联网 发布:以人为镜可以知得失 编辑:程序博客网 时间:2024/05/29 11:26

最近在读Problem Solving with Algorithms and Data Structures Using in python.

记录栈的应用。

栈(有时称为“后进先出栈”)是一个项的有序集合,其中添加移除新项总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。栈的底部很重要,因为在栈中靠近底部的项是存储时间最长的。最近添加的项是最先会被移除的。这种排序原则有时被称为 LIFO(last-in first-out),后进先出。它基于在集合内的时间长度做排序。较新的项靠近顶部,较旧的项靠近底部。栈的例子很常见。几乎所有的自助餐厅都有一堆托盘或盘子,你从顶部拿一个,就会有一个新的托盘给下一个客人。想象桌上有一堆书。只有顶部的那本书封面可见,要看到其他书的封面,只有先移除他们上面的书。

../_images/bookstack2.png

# -*- coding: utf-8 -*- 0.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)
利用python 模拟栈。

利用栈进行多种括号的匹配 () [] {}:

def parChecker(item):    s=Stack()    flag=0    for i in item:        if i in '([{':      #当i为([{时,将其压入栈            s.push(i)        elif  i in ')]}':       #当i为)]}时,判断栈的大小,如果不为0            if s.size()!=0:                if match(s.peek(),i):#调用match 判断i是否与栈顶元素匹配                    s.pop()                else:                    return flag            else:       #栈的大小,如果为0,直接返回flag                return flag    if s.size()==0:     #循环完整个item后,判断栈的大小,如果为空,则返回flag=1        flag=1    return flagdef match(item1,item2):    return '([{'.index(item1) == ')]}'.index(item2)

利用栈 进行进制转化。

def jinzhi(item,org,target):    flag=0    tmp=''    digits='0123456789ABCDEF'    s=Stack()    tmp_item=0    tmp_list=[i for i in str(item)]     # 将字符串输入转换成列表    while len(tmp_list):        #将item转换为10进制        tmp_item+=digits.index(tmp_list[0])*(org**(len(tmp_list)-1))        tmp_list=tmp_list[1:]    while  tmp_item >0:     #将得来的十进制数除以对应进制并压入栈中        s.push(tmp_item%target)        tmp_item=tmp_item//target    while not s.isEmpty():      #将栈中的各个数取出并重新得到目标进制的对应值        tmp=tmp+str(digits[s.pop()])    return tmpprint jinzhi('21021',3,15) #输入和输出都为str

后缀表达式
B*C=变量B被变量C乘,因为乘法符号*出现在两个表达式中间。这种表达式我们称之为中缀,因为操作符在变量的“中间”。

表达式A+B*C+D写成((A+(B*C))+D)表明先算乘法,再算左边的加法。A+B+C+D写成(((A+B)+C)+D)以表明从左到右。


把操作符放在操作数前面呢?变成*BC。放在后面呢?BC*

这两种变型形成新的格式,叫做前缀与后缀。前缀就是操作符放在他们的操作数前面,后缀就是放在后面。

用前缀方式,A+B*C就要写成 +A*BC,*放在B和C前面,+放在A和*BC的前面,乘法相对加法的优先级就体现出来了。

后缀表达式的情况下,A+B*C就要写成A B C * +。因为*紧跟B和C,当然是先算*,后算+。操作符可以前缀或后缀,但操作顺序完全相同。


再看一下中缀表达式(A+B)*C,中缀要求用括号来强制先算加法再算乘法。但前缀时,A+B写在+ A B,相加之和是后面乘法的第一个操作数,所以*就要移动到+A B 和C的前面,所以写成 * +A B C。类似的,后缀时,A B +强制先算加法,结果与C相乘,于是就写在 A B + C *。


注意 A+B+C+D的顺序有左逐渐到右,所以其前缀表达式是+++ABCD。后缀表达式是AB+C+D+,先算A+B,再加C最后加D。


将中缀转化为后缀:

1建立一个空栈,名为opstack保存操作符。建立空列表保存输出项。

把中缀表达式转为列表,使用split()方法。

从左到右扫描列表,对于每个元素:

如果是一个操作数,追加到输出列表

如果是左括号(,压栈到opstack

如果是右括号),循环出栈,直到左括号出栈。此前出栈的元素追加到输出列表

如果是操作符+-*/,先把栈内优先级大于当前操作符的项目全部出栈并追加到输出列表,然后把当前操作符压栈。

输入列表检索完成,检查栈,把剩下的元素全部出栈并加到输出列表尾部。


def houzhui(items):    s=Stack()    items_list=items.split()    shuchu_list=[]    digits='0123456789ABCDEFGHIJKLMNOPQRSTVUWXYZ'    sympl='*/+-'    dic={}      #确定各个运算符的优先级    dic['*']=3    dic['/']=3    dic['+']=2    dic['-']=2    dic['(']=1    for item in items:        if item in digits:      #将item压入列表            shuchu_list.append(item)        elif item =='(':    #当item为(,将其压入栈。            s.push(item)        elif item in sympl:         #把栈内优先级大于当前操作符的项目全部出栈并追加到输出列表            while not s.isEmpty() and dic[item]<dic[s.peek()] :                shuchu_list.append(s.pop())            s.push(item)        #将运算符压入栈        elif item==')':         #循环出栈,直到左括号出栈。            while s.peek()!= '(':                shuchu_list.append(s.pop())            s.pop()    while not s.isEmpty():      #输入列表检索完成,检查栈,把剩下的元素全部出栈并加到输出列表尾部。        shuchu_list.append(s.pop())    return ''.join(shuchu_list)     #将列表转为字符串print houzhui("(A * B + C) * D")print houzhui("( A + B ) * C - ( D - E ) * ( F + G )")

后缀表达式求值:

def count_houzhui(items):    s=Stack()    items=items.split()    digits='0123456789'    sympl='*/+-'    tmp=0    for item in items:        if item not in sympl:            s.push(item)        else:            tmp1=int(s.pop())            tmp2=int(s.pop())            if item =='+':                s.push(tmp2+tmp1)            elif item == '-':                s.push(tmp2-tmp1)            elif item == '*':                s.push(tmp2*(tmp1*1.0))            elif item == '/':                s.push(tmp2/(tmp1*1.0))    return int(s.pop())print count_houzhui('7 8 + 3 2 + /')




阅读全文
0 0
原创粉丝点击