栈(stack)
栈,堆栈,是一种容器,可存入数据元素、访问元素、删除元素。
它的特点在于只能允许在容器的一端(称为栈顶端指标,top)进行加入数据(push)和输出数据(pop)的运算。没有了位置概念,保证任何时候可以访问、删除的元素都是此前最后存入的那个元素,按照后进先出(LIFO, Last In First Out)的原理运作。
应用场景:函数调用。如:函数A调用B,B调用C,最后调用的C,但执行时是C先执行,返回,然后B执行,返回,A再执行,返回;在调用当前函数时会将局部变量和参数入栈,函数返回时会销毁当前函数的局部变量和参数,出栈。
队列(先进先出)是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
例如同样是在线性表中 "按顺序" 插入1,2,3,4:
对于栈,只允许在尾部删除,所以先出栈的将会是4,即后进先出;
对于队列,只允许在头部删除,所以先出队的是1,即先进先出。
用数组实现一个顺序栈
参考:https://blog.csdn.net/weixin_40283816/article/details/87890661
https://blog.csdn.net/mydistance/article/details/86024862
class SequenceStack:
def __init__(self):
self.MaxStackSize = 10
self.s = [None for x in range(0,self.MaxStackSize)]
self.top = -1
'''判断栈是否为空'''
def IsEmptyStack(self):
if self.top == -1:
iTop = True
else:
iTop = False
return iTop
'''进栈'''
def PushStaxk(self,x):
if self.top < self.MaxStackSize-1:
self.top = self.top+1
self.s[self.top] = x
else:
print("栈满")
return
'''出栈'''
def PopStack(self):
if self.IsEmptyStack == True:
print("栈为空")
return
else:
iTop = self.top
self.top = self.top-1
return self.s[iTop]
'''获取栈顶元素'''
def GetTopStack(self):
if self.IsEmptyStack == True:
return "栈为空"
else:
return self.s[self.top]
'''遍历栈内元素'''
def StackTraverse(self):
if self.IsEmptyStack == True:
return "栈为空"
else:
for i in range(0,self.top + 1):
print(self.s[i],end = ' ')
'''创建一个顺序栈'''
def CreateStackByInput(self):
data = input("请输入元素(确定按回车键,结束按“#”):")
while data != "#":
self.PushStaxk(data)
data = input("请输入元素(确定按回车键,结束按“#”):")
'''获取顺序栈的长度'''
def GetStackLength(self):
num = 0
for i in range(0,self.top + 1):
num = num+1
return num
ss = SequenceStack()
ss.CreateStackByInput()
print("栈内元素为:",end = " ")
ss.StackTraverse()
print("\n栈顶元素为:",ss.GetTopStack())
print("顺序栈的长度为:",ss.GetStackLength())
用链表实现一个链式栈
参考:https://www.cnblogs.com/cxc1357/p/10295369.html
https://blog.csdn.net/chenyuxiang0425/article/details/83422854
class Stack:
def __init__(self):
self._first = None
def push(self,item):
self._first = _Node(item,self._first)
def pop(self):
self._first = self._first.next
def isEmpty(self):
return self._first is None
class _Node:
def __init__(self,item,next):
self.item = item
self.next = next
def main():
stack = Stack()
stack.push("a")
stack.push("b")
stack.push("c")
print(stack._first.item)
print(stack._first.next.item)
print(stack._first.next.next.item)
if __name__ == "__main__":
main()
运行结果:
>> c
>> b
>> a
编程模拟实现一个浏览器的前进、后退功能
参考:https://github.com/wangzheng0822/algo/tree/master/python/08_stack
思路:我们使用两个栈,X 和 Y,我们把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈 X 中出栈,并将出栈的数据依次放入栈 Y。当我们点击前进按钮时,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。
import sys
# 引用当前文件夹下的single_linked_list
sys.path.append('linked_stack.py')
from linked_stack import LinkedStack
#from .linked_stack import LinkedStack
class NewLinkedStack(LinkedStack):
def is_empty(self):
return not self._top
class Browser():
def __init__(self):
self.forward_stack = NewLinkedStack()
self.back_stack = NewLinkedStack()
def can_forward(self):
if self.back_stack.is_empty():
return False
return True
def can_back(self):
if self.forward_stack.is_empty():
return False
return True
def open(self, url):
print("Open new url %s" % url, end="\n")
self.forward_stack.push(url)
def back(self):
if self.forward_stack.is_empty():
return
top = self.forward_stack.pop()
self.back_stack.push(top)
print("back to %s" % top, end="\n")
def forward(self):
if self.back_stack.is_empty():
return
top = self.back_stack.pop()
self.forward_stack.push(top)
print("forward to %s" % top, end="\n")
if __name__ == '__main__':
browser = Browser()
browser.open('a')
browser.open('b')
browser.open('c')
if browser.can_back():
browser.back()
if browser.can_forward():
browser.forward()
browser.back()
browser.back()
browser.back()
linked_stack.py
"""
Stack based upon linked list
基于链表实现的栈
"""
from typing import Optional
class Node:
def __init__(self, data: int, next=None):
self._data = data
self._next = next
class LinkedStack:
"""A stack based upon singly-linked list.
"""
def __init__(self):
self._top: Node = None
def push(self, value: int):
new_top = Node(value)
new_top._next = self._top
self._top = new_top
def pop(self) -> Optional[int]:
if self._top:
value = self._top._data
self._top = self._top._next
return value
def __repr__(self) -> str:
current = self._top
nums = []
while current:
nums.append(current._data)
current = current._next
return " ".join(f"{num}]" for num in nums)
if __name__ == "__main__":
stack = LinkedStack()
for i in range(9):
stack.push(i)
print(stack)
for _ in range(3):
stack.pop()
print(stack)
队列
用数组实现一个顺序队列
参考:http://www.cnblogs.com/dairuiquan/p/10380504.html
https://github.com/wangzheng0822/algo/blob/master/python/09_queue/array_queue.py
# 数组有一个固定的长度。头指针和尾指针,都指向数组第一个值。
# 当进行push操作的时候,头指针后移。当进行pop操作的时候,尾指针向后移
# 当到达最后一个值的时候,重新指向第一个值。取模 %queue_size()
# 首先实现一个数组
class Array(object):
def __init__(self,size = 32):
self._size = size
self._items = [None] * size # 容器_items, 是一个每个值为None的列表
def __getitem__(self, index): # 实现下标访问
return self._items[index]
def __setitem__(self, index, value):
self._items[index] = value
def __len__(self):
return self._size
def clear(self, value=None):
for i in range(len(self._items)):
self._items[i] = value
def __iter__(self):
for item in self._items:
yield item
class ArrayQueue(object):
def __init__(self, maxsize):
self.maxsize = maxsize
self.array = Array(maxsize)
self.head = 0
self.tail = 0
def push(self, value):
if len(self) >= self.maxsize:
raise Exception('queue full')
self.array[self.head % self.maxsize] = value
self.head += 1
def pop(self):
value = self.array[self.tail % self.maxsize]
self.tail += 1
return value
def __len__(self):
return self.head - self.tail
用链表实现一个链式队列
参考:https://blog.csdn.net/weixin_40283816/article/details/87952682
https://github.com/wangzheng0822/algo/blob/master/python/09_queue/linked_queue.py
链式队列在创建一个队列时,队头指针front和队尾指针rear指向结点的data域和next域均为空。
class QueueNode():
def __init__(self):
self.data = None
self.next = None
class LinkQueue():
def __init__(self):
tQueueNode = QueueNode()
self.front = tQueueNode
self.rear = tQueueNode
'''判断是否为空'''
def IsEmptyQueue(self):
if self.front == self.rear:
iQueue = True
else:
iQueue = False
return iQueue
'''进队列'''
def EnQueue(self,da):
tQueueNode = QueueNode()
tQueueNode.data = da
self.rear.next = tQueueNode
self.rear = tQueueNode
print("当前进队的元素为:",da)
'''出队列'''
def DeQueue(self):
if self.IsEmptyQueue():
print("队列为空")
return
else:
tQueueNode = self.front.next
self.front.next = tQueueNode.next
if self.rear == tQueueNode:
self.rear = self.front
return tQueueNode.data
def GetHead(self):
if self.IsEmptyQueue():
print("队列为空")
return
else:
return self.front.next.data
def CreateQueueByInput(self):
data = input("请输入元素(回车键确定,#结束)")
while data != "#":
self.EnQueue(data)
data = input("请输入元素(回车键确定,#结束)")
'''遍历顺序队列内的所有元素'''
def QueueTraverse(self):
if self.IsEmptyQueue():
print("队列为空")
return
else:
while self.front != self.rear:
result = self.DeQueue()
print(result,end = ' ')
lq = LinkQueue()
lq.CreateQueueByInput()
print("队列里元素为:")
lq.QueueTraverse()
实现一个循环队列
参考:https://blog.csdn.net/u012626619/article/details/80658397
https://github.com/wangzheng0822/algo/blob/master/python/09_queue/circular_queue.py
http://www.cnblogs.com/xiaxuexiaoab/p/8593146.html
class SqQueue(object):
def __init__(self, maxsize):
self.queue = [None] * maxsize
self.maxsize = maxsize
self.front = 0
self.rear = 0
# 返回当前队列的长度
def QueueLength(self):
return (self.rear - self.front + self.maxsize) % self.maxsize
# 如果队列未满,则在队尾插入元素,时间复杂度O(1)
def EnQueue(self, data):
if (self.rear + 1) % self.maxsize == self.front:
print("The queue is full!")
else:
self.queue[self.rear] = data
# self.queue.insert(self.rear,data)
self.rear = (self.rear + 1) % self.maxsize
# 如果队列不为空,则删除队头的元素,时间复杂度O(1)
def DeQueue(self):
if self.rear == self.front:
print("The queue is empty!")
else:
data = self.queue[self.front]
self.queue[self.front] = None
self.front = (self.front + 1) % self.maxsize
return data
# 输出队列中的元素
def ShowQueue(self):
for i in range(self.maxsize):
print(self.queue[i],end=',')
print(' ')
# 测试程序
if __name__ == "__main__":
# 建立大小为15的循环队列
q = SqQueue(15)
# 0~9入队列
for i in range(10):
q.EnQueue(i)
q.ShowQueue()
# 删除队头的5个元素:0~4
for i in range(5):
q.DeQueue()
q.ShowQueue()
# 从队尾增加8个元素:0~7
for i in range(8):
q.EnQueue(i)
q.ShowQueue()
递归
编程实现斐波那契数列求值 f(n)=f(n-1)+f(n-2)
参考:https://blog.csdn.net/weixin_42793426/article/details/82996658
# 递归方式实现 生成前20项
lis =[]
for i in range(20):
if i ==0 or i ==1:#第1,2项 都为1
lis.append(1)
else:
lis.append(lis[i-2]+lis[i-1])#从第3项开始每项值为前两项值之和
print(lis)
def func(n):
# 给递归一个出口 第一位和第二位都是1
if n == 1 or n == 2:
return 1
else:
# 从第三位开始 返回上一个数加上上一个数
return func(n-1) + func(n-2)
res = func(20)
print(res)
编程实现求阶乘 n!
参考:https://www.cnblogs.com/iderek/p/5969992.html
def f(x):
if x == 0:
return 0
elif x == 1:
return 1
else:
return (x * f(x-1))
print(f(5))
编程实现一组数据集合的全排列
参考:https://blog.csdn.net/zhoufen12345/article/details/53560099
COUNT=0
def perm(n,begin,end):
global COUNT
if begin>=end:
print n
COUNT +=1
else:
i=begin
for num in range(begin,end):
n[num],n[i]=n[i],n[num]
perm(n,begin+1,end)
n[num],n[i]=n[i],n[num]
n=[1,2,3,4]
perm(n,0,len(n))
print COUNT