堆栈:先进后出,队列:先进先出
堆栈是一种线性表,只能在表尾进行插入和删除操作,这个表尾就是栈顶,另一端就是栈底。那么向堆栈插入新元素就叫做入栈、进栈或压栈,也就是将新元素放到栈顶;反之出栈时,就是把栈顶元素删除,使其相邻元素成为新的栈顶。
队列也是一种线性表,只允许在表的前端(front)进行删除操作,在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
下面我们通过多种方法来实现,让初学者更熟悉这两种数据结构。
class Stack:
#初始化一个列表,定义一个大小
def __init__(self):
self.stack=[]
self.size=0
#打印的时候,方便输出这个字符串
def __str__(self):
return str(self.stack)
#入栈
def push(self,data):
self.stack.append(data)
self.size+=1
#出栈
def pop(self):
if self.stack is not None:
tmp=self.stack.pop()
self.size-=1
return tmp
#栈顶元素
def top(self):
if self.stack is not None:
return self.stack[-1]
#是否空栈
def is_empty(self):
return not bool(self.stack)
stack=Stack()
stack.push(1)
stack.push(2)
stack.push('寅恪光潜')
stack.push(3)
stack.push('Tony')
stack.pop()
stack.pop()
#print(stack.stack)
print(stack,stack.size,stack.is_empty(),stack.top())
#[1, 2, '寅恪光潜'] 3 False 寅恪光潜
from typing import Any, NoReturn, Optional
#定义一个结点类
class Node:
#Any指任意类型,Optional为可选类型,先设置为空
def __init__(self,data:Any,next:Optional=None):
self.data:Any=data
self.next:Optional[Node]=next
#方便打印显示
def __str__(self):
return "Node:%s" % self.data
class LinkedStack:
#栈顶初始化为空,大小为0
def __init__(self)->NoReturn:
self.top=None
self.size=0
#入栈
def push(self,item:Any)->None:
node=Node(item)#生成结点数据
#如果栈顶有数据,将栈顶数据向下移动,然后栈顶接收新数据
#如果栈顶为空,将新数据赋值给栈顶
if self.top:
node.next=self.top
self.top=node
else:
self.top=node
self.size+=1
#出栈
def pop(self)->Any:
#如果栈顶有节点,将下一个结点赋值到栈顶
#如果栈顶为空,不能出栈
if self.top:
node:Node=self.top
self.top=node.next
self.size-=1
return node.data
else:
raise IndexError("空栈不能有出栈操作")
#是否空栈
def is_empty(self)->bool:
return self.top is None
#重构,与__str__有些许区别
def __repr__(self):
current=self.top
string_repr=""
while current:
string_repr+=f"{current} --> "
current=current.next
return string_repr +"栈底"
linedstack=LinkedStack()
linedstack.push(11)
linedstack.push(22)
linedstack.pop()
linedstack.push('寅恪光潜')
linedstack.push('Tony')
linedstack.push(33)
print(linedstack)
print(linedstack.size)
'''
Node:33 --> Node:Tony --> Node:寅恪光潜 --> Node:11 --> 栈底
4
'''
其中在方法名后面出现 ->返回类型,它是对返回类型的一种注解,如下,比如可以获取查看push方法的类型
print(linedstack.push.__annotations__)#{'item': typing.Any, 'return': None}
然后我们来看下怎么实现队列,熟悉上面之后,写起来就很简单了。
class Queue:
def __init__(self):
self.enteries=[]
self.length=0
self.front=0
def __str__(self):
return "<"+str(self.enteries)[1:-1]+">"
#入队
def put(self,item):
self.enteries.append(item)
self.length +=1
#出队,返回第一个,只保留从第二个开始的数据
def get(self):
dequeued=self.enteries[self.front]
self.enteries=self.enteries[1:]
self.length=self.length-1
return dequeued
def size(self):
return self.length
queue=Queue()
queue.put("One")
queue.put("Two")
queue.put("Three")
queue.get()
queue.put("Tony")
print(queue)
print(queue.size())
print(queue.enteries[0])
'''
<'Two', 'Three', 'Tony'>
3
Two
'''
from typing import Any, Optional
class Node:
#Any指任意类型,Optional为可选类型,先设置为空
def __init__(self,data:Any,next:Optional=None):
self.data:Any=data
self.next:Optional[Node]=next
#方便打印显示
def __str__(self):
return "Node:%s" % self.data
class LinkedQueue:
def __init__(self)->None:
self.front:Optional[Node]=None
self.rear:Optional[Node]=None
self.size=0
#入队,就是节点后面的下一节点接收新节点数据
def put(self,item:Any)->None:
node:Node=Node(item)
if self.is_empty():
self.front=node
self.rear=node
else:
self.rear.next=node
self.rear=node
self.size +=1
#出队,就是下一节点放在前面,向前推进一位
def pop(self):
if self.is_empty():
raise IndexError("空队列不能出队操作")
else:
node:Node=self.front
self.front=node.next
self.size-=1
def is_empty(self)->bool:
return self.front is None
def __repr__(self):
current=self.front
string_repr=""
while current:
string_repr +=f"{current}<--"
current=current.next
return string_repr+"队列尾部"
linkedqueue=LinkedQueue()
linkedqueue.put("One")
linkedqueue.put("Tony")
linkedqueue.put("寅恪光潜")
linkedqueue.put("Two")
linkedqueue.put("Three")
linkedqueue.pop()
print(linkedqueue)
'''
Node:Tony<--Node:寅恪光潜<--Node:Two<--Node:Three<--队列尾部
'''