一、课程目标
- 什么是栈
- 栈的python实现
二、详情解读
- 什么是栈
栈中必须亦第一个元素和最后一个元素
对栈的操作只能从某一端操作,即栈顶
栈的数据访问遵从LIFO(last-in first-out)协议
- 栈的python实现
方法 | 说明 |
---|---|
s.isEmpty() | 栈是否为空 |
s.__ len __() | 栈中的项目数 |
s.push() | 在栈顶压入一项 |
s.top() | 如果s不为空,返回顶部第一项,否则抛出错误 |
s.pop() | 如果s不为空,返回并删除第一项,否则抛出错误EmptyError |
列表实现
使用列表实现栈,可以从列表末尾压入与弹出,因为从末尾操作的时间复杂度是O(1),其他位置操作是O(n)
由于列表是一个动态数组,当栈的变化引起列表内存占用变大时,会引起性能的损耗。因此数据变化大时不宜用列表实现栈。
class EmptyError(Exception):
def __init__(self,errno,error):
self.errno=errno
self.error=error
class ListStack:
def __init__(self):
self.data=[]
def __len__(self):
return len(self.data)
def isEmpty(self):
return len(self.data)==0
def checkEmpty(self):
if self.isEmpty():
raise EmptyError(1,'stack is empty')
def push(self,data):
self.data.append(data)
def pop(self):
self.checkEmpty()
return self.data.pop()
def top(self):
self.checkEmpty()
return self.data[-1]
mystack=ListStack()
for i in range(10):
mystack.push(i)
print(mystack)
while True:
try:
print(mystack.pop())
except EmptyError:
break
链表实现栈
1.使用链表实现栈,可以从链表首部压入与弹出
2.随着栈的增大,链表的内存占用线性增长
class Node:
def __init__(self,data,next=None):
self.data=data
self.next=next
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self,new_data):
self.data=new_data
class LinkedList:
def __init__(self):
self.head=None
self.length=0
def __len__(self):
return self.length
def insert_head(self,node):
'''
插入节点
'''
self.head,node.next=node,self.head
self.length+=1
def __iter__(self):
'''
遍历链表
'''
head=self.head
while head is not None:
current,head=head,head.next
yield current
def append_node(self,node):
'''
末尾插入
:param node:
:return:
'''
current=self.head
while current.next is not None:
current=current.next
current.next=node
self.length+=1
def pop_first(self):
'''
弹出并返回第一个元素
:return:
'''
head=self.head
if self.head is not None:
self.head=self.head.next
self.length-=1
return head
def pop_last(self):
'''
弹出最后一个节点
:return:
'''
current=self.head
while current.next.next is not None:
current=current.next
node,current.next=current.next,None
self.length-=1
return node
def insert(self,index,new_node):
'''
在第index处插入数据
:param index:
:param new_node:
:return:
'''
if self.head is None or index<1:
self.head,new_node.next=new_node,self.head
else:
current=self.head
while index>1 and current.next is not None:
current=current.next
index-=1
current.next,new_node.next=new_node,current.next
self.length+=1
def remove(self,index):
'''
移除
:param index:
:return:
'''
if self.head is None or index<0:
return None
else:
current=self.head
while index>1 and current.next is not None:
current=current.next
index-=1
current.next=current.next.next
self.length-=1
from linkedist import Node,LinkedList
class EmptyError(Exception):
def __init__(self,errno,error):
self.errno=errno
self.error=error
class LinkedStack:
def __init__(self):
self.data=LinkedList()
def __len__(self):
return len(self.data)
def isEmpty(self):
return len(self.data)==0
def push(self,data):
node=Node(data)
self.data.insert_head(node)
def checkEmpty(self):
if self.isEmpty():
raise EmptyError(2,'stack is empty')
def pop(self):
self.checkEmpty()
return self.data.pop_first().data
def top(self):
self.checkEmpty()
return self.data.head.data
linkedstack=LinkedStack()
for i in range(10):
linkedstack.push(i)
while not linkedstack.isEmpty():
print(linkedstack.pop())
- 栈的时间复杂度
无论是压入或者弹出,栈的时间复杂度始终是O(1)。