本文是学习陆老师的《python全栈工程师 - 数据结构与算法》课程的笔记,欢迎学习交流。同时感谢陆老师的精彩传授!
一、课程目标
- 什么是栈
- 栈的python实现
二、详情解读
01.什么是栈: 栈是一种线性表
1.栈中必须有第一个元素与最后一个元素
2.对栈的操作只能从某一端操作,即栈顶(top)
3.栈的数据访问遵从LIFO(last-in first-out)协议
02.栈(stack)的python实现:
1).栈的方法(主要方法列表)
方法 | 说明 |
---|---|
s.isEmpty() | 栈是否为空 |
s.__ len __() | 栈中的项目数 |
s.push() | 在栈顶压入一项 |
s.top() | 如果s不为空,返回顶部第一项,否则抛出错误EmptyError |
s.pop() | 如果s不为空,返回并删除第一项,否则抛出错误EmptyError |
2).栈的实现
列表实现
1.使用列表实现栈,可以从列表末尾压入与弹出(因为从末尾操作时间复杂度为O(1),其他位置操作是O(n))
2.由于列表是一个动态数组,当栈的变化引起列表内存占用变大时,会引起性能的损耗
因此数据变化大时不宜用列表实现栈
'''
用列表实现的栈
'''
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.随着栈的增大,链表的内存占用线性增长
from linkedlist 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 checkEmpty(self):
if self.isEmpty():
raise EmptyError(2, 'stack is empty')
def push(self, data):
node = Node(data)
self.data.insert_head(node)
def pop(self):
self.checkEmpty()
return self.data.pop_first().data
def top(self):
self.checkEmpty()
return self.data.head.data
# linkedlist.py文件
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):
'''
末尾插入节点
'''
current = self.head
while current.next is not None:
current = current.next
current.next = node
self.length += 1
def pop_first(self):
'''
弹出并返回第一个节点
'''
head = self.head
if self.head is not None:
self.head = self.head.next
self.length -= 1
return head
def pop_last(self):
'''
弹出最后一个节点
'''
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处插入数据
'''
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):
'''
删除index处节点
'''
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
03.栈的时间复杂度
栈的压入与弹出时间复杂度
无论是压入或者弹出,栈的时间复杂度始终是O(1)
三、课程小结
- 学习了栈的概念
- 学习了栈的python实现
- 学习了栈的时间复杂度