python 栈

       栈是线性的集合,其中,访问都严格的限制在一端,也叫作顶(top)。栈是遵从后进先出(LIFO)的协议,从栈放入项和从栈删除项的操作分别叫压人(push)和弹出(pop)。

       栈并不是Python的内建类型,Python程序员在必要的时候可以使用列表来模拟基于数组的栈。如果将列表的末尾看作是栈的顶,列表方法append就是将元素压入到栈中,而列表方法pop会删除并返回栈顶的元素。

       栈的应用:

  • 将中缀表达式转换为后缀表达式,并且计算后缀表达式
  • 回溯算法
  • 管理计算机内存以支持函数和方法调用
  • 支持文本编辑器、字处理程序、电子表格程序、绘图程序或类似的应用程序中的撤销功能
  • 维护Web浏览器所访问过的连接的历史记录

一、中缀表达式转换为后缀表达式 

中缀表达式转后缀表达式的规则:

1.遇到操作数,直接输出; 
2.栈为空时,遇到运算符,入栈; 
3.遇到左括号,将其入栈; 
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出; 
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈; 
6.最终将栈中的元素依次出栈,输出。 
经过上面的步骤,得到的输出既是转换得到的后缀表达式。 

def middle2behind(expresssion):  
    result = []             # 结果列表
    stack = []              # 栈
    for item in expression: 
        if item.isnumeric():      # 如果当前字符为数字那么直接放入结果列表
            result.append(item) 
        else:                     # 如果当前字符为一切其他操作符
            if len(stack) == 0:   # 如果栈空,直接入栈
                stack.append(item)
            elif item in '*/(':   # 如果当前字符为*/(,直接入栈
                stack.append(item)
            elif item == ')':     # 如果右括号则全部弹出(碰到左括号停止)
                t = stack.pop()
                while t != '(':   
                    result.append(t)
                    t = stack.pop()
            # 如果当前字符为加减且栈顶为乘除,则开始弹出
            elif item in '+-' and stack[len(stack)-1] in '*/':
                if stack.count('(') == 0:           # 如果有左括号,弹到左括号为止     
                    while stack:
                        result.append(stack.pop())
                else:                               # 如果没有左括号,弹出所有
                    t = stack.pop()
                    while t != '(':
                        result.append(t)
                        t = stack.pop()
                    stack.append('(')
                stack.append(item)  # 弹出操作完成后将‘+-’入栈
            else:
                stack.append(item)# 其余情况直接入栈(如当前字符为+,栈顶为+-)

    # 表达式遍历完了,但是栈中还有操作符不满足弹出条件,把栈中的东西全部弹出
    while stack:
        result.append(stack.pop())
    # 返回字符串
    return "".join(result)

expression = "3+(6*7-2)+2*3"
print(middle2behind(expression))

二、后缀表达式计算

def postfix_calculate(s):
    """注意-号和/号的顺序问题"""
    stack=[]
    for x in s:
        if x.isdigit():   #如果字符是数字
            stack.append(x)
        elif x == "+":
            a = stack.pop()
            b = stack.pop()
            stack.append(int(a)+int(b))
        elif x == "-":
            a = stack.pop()
            b = stack.pop()
            stack.append(int(b)-int(a))
        elif x == "*":
            a = stack.pop()
            b = stack.pop()
            stack.append(int(a)*int(b))
        elif x == "/":
            a = stack.pop()
            b = stack.pop()
            stack.append(int(b)/int(a))
 
    return stack[len(stack)-1]

三、回溯算法

       回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

       主要有两种技术来实现回溯算法:一种是使用栈,还有一种是使用递归。下面介绍使用栈来实现回溯算法,在这个过程中,栈的作用是在每一个关头记住可替代的状态。

题目描述

定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示: 

int maze[5][5] = {

        0, 1, 0, 0, 0,

        0, 1, 0, 1, 0,

        0, 0, 0, 0, 0,

        0, 1, 1, 1, 0,

        0, 0, 0, 1, 0,

};

表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],即第一空格是可以走的路。

Input

一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input

0 1 0 0 0

0 1 0 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

Sample Output

(0, 0)

(1, 0)

(2, 0)

(2, 1)

(2, 2)

(2, 3)

(2, 4)

(3, 4)

(4, 4)

分析

元素--状态空间分析:每个坐标是是一个元素,每次可以在上一个坐标基础上向右[0,1]或者向下[1,0]移动一步。所以这里可以看出,元素是不固定的,状态空间固定。

 

maze = [
	[0,1,0,0,0],
	[0,1,1,1,0],
	[0,1,0,0,0],
	[0,1,0,1,0],
	[0,0,0,1,0]
]
dirs = [
    lambda x,y:(x+1,y),#下
    lambda x,y:(x-1,y),#上
    lambda x,y:(x,y-1),#左
    lambda x,y:(x,y+1),#右
]

def maze_path(x1,y1,x2,y2):
	stack = []
	stack.append((x1,y1))
	while(len(stack)>0):
		biz=0
		curNode=stack[-1] # 当前的节点
		if curNode[0]==x2 and curNode[1]==y2:
            # 走到终点了
			for p in stack:
				print(p)
			return True
        # x,y 四个方向:上 x-1,y, 右 x,y+1, 下 x+1,y, 左 x,y-1
		for dir in dirs:
			nextNode = dir(curNode[0],curNode[1])
			if nextNode[0]>4 or nextNode[0]<0 or nextNode[1]<0 or nextNode[1]>4:
				continue
			if maze[nextNode[0]][nextNode[1]] == 0:
				stack.append(nextNode)
				maze[nextNode[0]][nextNode[1]] = 2  #避免走回头路
				biz=1
				break
		if biz==0:
			stack.pop()
	print('没有路')
	return False
maze_path(0,0,4,4)

以上三个关于栈的实例中都有采用列表模拟,但python中有专门的模块定义了栈:

 栈的相关操作如下:

  • Stack() 创建一个空的新栈。 它不需要参数,并返回一个空栈。
  • push(item)将一个新项添加到栈的顶部。它需要 item 做参数并不返回任何内容。
  • pop() 从栈中删除顶部项。它不需要参数并返回 item 。栈被修改。
  • peek() 从栈返回顶部项,但不会删除它。不需要参数。 不修改栈。
  • isEmpty() 测试栈是否为空。不需要参数,并返回布尔值。
  • size() 返回栈中的 item 数量。不需要参数,并返回一个整数。

 下表展示了栈的操作序列结果:
这里写图片描述

以下栈实现代码假定列表的结尾将保存栈的顶部元素。随着栈增长(push 操作),新项将被添加到列表的末尾。 pop 也操作列表末尾的元素。 

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)

记住我们只定义类的实现,我们需要创建一个栈,然后使用它。以下代码展示了我们通过实例化 Stack 类执行 栈的操作。注意,Stack 类的定义是从 pythonds 模块导入的。

from pythonds.basic.stack import Stack

s=Stack()

print(s.isEmpty())
s.push(4)
s.push('dog')
print(s.peek())
s.push(True)
print(s.size())
print(s.isEmpty())
s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())

四、十进制转换为二进制

       “除 2” 算法假定我们从大于 0 的整数开始。不断迭代的将十进制除以 2,并跟踪余数。第一个除以 2 的余数说明了这个值是偶数还是奇数。偶数有 0 的余数,记为 0。奇数有余数 1,记为 1.我们将得到的二进制构建为数字序列,第一个余数实际上是序列中的最后一个数字。见 Figure 5 , 我们再次看到了反转的属性,表示栈可能是解决这个问题的数据结构。

 

from pythonds.basic.stack import Stack
def divideBy2(decNumber):
	remstack = Stack()
	while decNumber!=0:
		num=decNumber%2
		remstack.push(num)
		decNumber//=2
	binString=''
	while not remstack.isEmpty()!=0:
		binString+=str(remstack.pop())
	return binString
print(divideBy2(12))

 

  • 13
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python的基本操作包括入(push)、出pop)、获取顶元素(speek)、判断是否为空(is_empty)和获取中元素个数(size)。可以使用数组实现的数据结构,也可以使用列表实现的功能。 使用数组实现的示例代码如下: ```python class MyStack: def __init__(self): self.items = [] def isEmpty(self): return len(self.items) == 0 def size(self): return len(self.items) def top(self): if not self.isEmpty(): return self.items[len(self.items)-1] else: return None def pop(self): if len(self.items) > 0: return self.items.pop() else: print("已为空!") return None def push(self, item): self.items.append(item) if __name__ == "__main__": s = MyStack() s.push(6) s.push(3) print("顶元素为:" + str(s.top())) print("大小为:" + str(s.size())) s.pop() print("出成功!") print("顶元素为:" + str(s.top())) print("大小为:" + str(s.size())) s.pop() print("出成功!") s.pop() ``` 使用列表实现的示例代码如下: ```python class Stack: def __init__(self): self.__list = [] def push(self, item): self.__list.append(item) def pop(self): return self.__list.pop() def speek(self): return self.__list[-1] def is_empty(self): return not self.__list def size(self): return len(self.__list) if __name__ == '__main__': s = Stack() c = 1 s.push('a') s.push('b') s.push(c) print('size:', s.size()) print('speek:', s.speek()) print(s.pop()) print(s.pop()) print(s.pop()) print('size:', s.size()) ``` 以上是Python的基本操作的示例代码。可以根据需要选择使用数组实现,或者使用列表实现。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [python算法——实现的基本操作](https://blog.csdn.net/xjtuse123/article/details/98451560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [python 的基本操作](https://blog.csdn.net/qq_38779236/article/details/92693703)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值