python栈和队列
- 一、栈
- 1. 栈的基本介绍
- 2. 代码
- 3. 基本操作
- 4. 括号匹配问题
- 5. 删除字符串所有相邻的重复项
- 6. 出栈顺序是否合法
- 二、队列
- 1. 队列基本介绍
- 2. 队列代码
- 3. 队列基本操作
- 4. 约瑟夫环-循环嵌套
- 5. 约瑟夫环-队列1
- 6. 约瑟夫环-队列2
一、栈
1. 栈的基本介绍
特点:先进后出 (last-in, first-out)
入栈:push()
出栈:pop()
栈顶:get_top()
栈中元素个数:size()
判断栈是否为空:empty()
2. 代码
class Stack():
def __init__(self):
self.stack = []
def push(self, element): # 入栈
self.stack.append(element)
def pop(self): # 出栈
return self.stack.pop()
def empty(self): # 判断栈是否为空
return self.stack == []
def size(self): # 返回栈中元素数量
return len(self.stack)
def get_top(self):# 取栈顶元素
if len(self.stack) > 0:
return self.stack[-1]
else:
return None
3. 基本操作
4. 括号匹配问题
class Stack():
def __init__(self):
self.stack = []
def push(self, element):
self.stack.append(element)
def pop(self):
return self.stack.pop()
def get_top(self):
if len(self.stack) > 0:
return self.stack[-1]
else:
return None
def empty(self):
return len(self.stack) == 0
def bracket(s):
stack = Stack()
if len(s) % 2 != 0: # 如果括号可以匹配,那么数量一定为偶数
return False
for i in s:
if i == '(':
stack.push(')')
elif i == '[':
stack.push(']')
elif i == '{':
stack.push('}')
elif stack.get_top() == i:
stack.pop()
elif stack.empty() or stack.get_top() != i:
return False
if stack.empty():
return True
else:
return False
s = input(':')
print(bracket(s))
5. 删除字符串所有相邻的重复项
样例:
输入:"abbaca"
输出:"ca"
例如:
在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。
之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
class Stack():
def __init__(self):
self.stack = []
def push(self, element):
self.stack.append(element)
def pop(self):
return self.stack.pop()
def get_top(self):
if len(self.stack) > 0:
return self.stack[-1]
else:
return None
def empty(self):
return len(self.stack) == 0
def bracket(s):
stack = Stack()
for i in s:
# 1. 如果栈为空 或者 前一个元素(栈顶)不等于当前元素i,则代表不是重复的,直接入栈即可
if stack.empty() or stack.get_top() != i:
stack.push(i)
# 2. 如果前一个元素(栈顶) 等于 当前元素i,则需要出栈
elif i == stack.get_top():
stack.pop()
# 3. 挨个遍历栈里面的元素,并加入到s中。注意:因为是从栈顶依次获取的,所有字符串s需要反转。
s = ""
while not stack.empty():
s += stack.get_top()
stack.pop()
return s[::-1]
s = input(':')
print(bracket(s))
6. 出栈顺序是否合法
输入出栈的数字(数字不相同),判断这些数字是否可以合法入栈。
class Stack():
def __init__(self):
self.stack = []
def push(self, element):
self.stack.append(element)
def pop(self):
return self.stack.pop()
def get_top(self):
if len(self.stack) > 0:
return self.stack[-1]
else:
return None
def empty(self):
return len(self.stack) == 0
# ① 创建栈,stack为栈中
stack = Stack()
# ② 创建数组a,为栈后数组
a = [0 for i in range(10)]
# ③ 输入数字
n = int(input('你要输入几个数字:'))
for i in range(1, n + 1):
a[i] = int(input('请输入数字:'))
print(a)
# ④ 入栈、出栈
p = 1 # p表示栈前,p始终指向它即将入栈的那一位
flag = 1
for i in range(1, n + 1):
while a[i] >= p: # 将i之前的所有数字入栈
stack.push(p) # 入栈
p += 1
if stack.get_top() == a[i]: # 如果栈顶 等于 列表第i为的元素,出栈
stack.pop() # 出栈
else:
flag = 0
break
# ⑤ 判断是否合法
if flag:
print(True)
else:
print(False)
二、队列
1. 队列基本介绍
特点:先进先出 (First in,First out)
入队:push()。队尾(rear)指针加1。rear=(rear+1)%MaxSize
出队:pop()。 对头(front)指针加1。front=(front+1)%MaxSize
对头元素:get_front()
对尾元素:get_back()
队列中元素个数:length()。(rear−front+MaxSize)%MaxSize
判断队是否为空:empty()。front==rear
判断队列是否满:filled()。(rear+1)%MaxSize==front
2. 队列代码
class Queue:
def __init__(self, size):
self.queue = [0 for _ in range(size)]
self.size = size # 队列最大容量
self.rear = 0 # 队尾,负责入队
self.front = 0 # 队头,负责出队
# 入队
def push(self, element):
if not self.filled(): # 如果队不满,则入队
self.rear = (self.rear + 1) % self.size # 将队尾指针重新赋值,队尾需要向后移动一位
self.queue[self.rear] = element # 队尾插入元素
else:
raise IndexError("队列已满!!!")
# 出队
def pop(self):
if not self.empty(): # 如果队不空,则出队
self.front = (self.front + 1) % self.size # 将队头指针重新赋值,对头需要向后移动一位
return self.queue[self.front]
else:
raise IndexError("队列为空!!!")
# 判断队空(队头等于队尾则代表对空)
def empty(self):
return self.rear == self.front
# 判断队满
def filled(self):
return (self.rear + 1) % self.size == self.front
# 队列元素个数
def length(self):
return (self.rear - self.front + self.size) % self.size
# 对头元素
def get_front(self):
if not self.empty(): # 如果队不空,则打印对头元素
return self.queue[(self.front + 1) % self.size]
# 对尾元素
def get_back(self):
if not self.empty(): # 如果队不空,则打印对尾元素
return self.queue[self.rear]
3. 队列基本操作
# 1. 创建队列
q = Queue(5)
# 2. 依次添加数据
q.push(1)
q.push(2)
q.push(3)
q.push(4)
# 3. 出队列
print('出队:', q.pop())
print('出队:', q.pop())
# 4. 长度、对头、队尾
print('队列长度:', q.length())
print('对头元素:', q.get_front())
print('对尾元素:', q.get_back())
# ⑤ 遍历队列
# while not q.empty():
# print(q.pop())
while not q.empty():
print('对头元素:', q.get_front())
q.pop()
4. 约瑟夫环-循环嵌套
一共有n个人,第m个人负责出圈,请依次打印出圈的数字。
a = [0 for i in range(101)]
n, m, i, cnt, k = 0, 0, 0, 0, 0 # cnt:出圈人数 i:位置,从1开始 k:数数,到k,就要出圈
n = int(input('一共有几个人?'))
m = int(input('第几个人出圈?'))
while cnt != n:
i += 1
if i > n: # 走到了最后一个,再回头
i = 1
if a[i] == 0: # 如果为0则代表这个数还没出圈
k += 1
if k == m:
a[i] = 1 # 出圈
cnt += 1 # 出圈人数增加1
print(i, end=' ')
k = 0 # 重新数数
5. 约瑟夫环-队列1
# 1. 创建队列
q = Queue(20)
n = int(input('一共有几个人?'))
m = int(input('第几个人出圈?'))
# 2. 将n个人的编号按顺序依次入队
for i in range(1, n + 1):
q.push(i)
# 3. 从1开始报数10
cnt = 1
while not q.empty(): # 只要队列不为空则一直循环
if cnt % m == 0: # 代表找到了
print(q.get_front(), end=' ')
q.pop()
cnt = 0
else: # 未找到
q.push(q.get_front()) # 把队头元素调到队尾
q.pop()
cnt += 1
6. 约瑟夫环-队列2
# 1. 创建队列
q = Queue(20)
n = int(input('一共有几个人?'))
m = int(input('第几个人出圈?'))
# 2. 将n个人的编号按顺序依次入队
for i in range(1, n + 1):
q.push(i)
# 3. 将第m个数字移到队首,第m-1个数字移到队尾
while q.length() > 0: # 删除操作,并在当队列中没有数字时停止该操作
for i in range(1, m): # 将队列中第m个人移到队首,并将前面m-1个人按顺序排到队尾
h = q.get_front()
q.pop()
q.push(h)
x = q.pop()
print(x, end=' ')