数据结构
数据结构的分类
数据结构有逻辑结构和物理结构,物理结构就是在计算机中如何表示的,这里我们只关注逻辑结构。
树结构只能从父节点指向孩子结点,如果将孩子结点指向上级的结点就构成了图结构,图结构是多对多的关系。
列表/数组
下图中,左边是C语言中的数组,右边是python中的列表。列表的元素类型可以不一样,因为python开辟了新的内存用来存放列表元素的值,列表存放的只是指向元素的地址。按下标查找元素,只需要根据首地址+index*length即可得到该元素的地址,返回数组元素,或者根据地址得到列表元素再返回,时间复杂度都是O(1)。而插入元素和删除元素,后面的元素都得跟着移动,故时间复杂度为O(n)。
栈
栈的实现
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
stack=Stack
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop())
栈的应用——括号匹配问题
遇到左括号进栈,遇到右括号,则与栈顶元素比较,一样则出栈,全部判断完后,栈为空则匹配成功。
# ()[][{()[]}]
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 is_empty(self):
return len(self.stack) == 0
def brace_match(s):
match = {'}':'{', ']':"[", ')':'('}
stack = Stack()
for ch in s:
if ch in {'(','[','{'}:
stack.push(ch)
else: #ch in {'}',']',')'}
if stack.is_empty():
return False
elif stack.get_top() == match[ch]:
stack.pop()
else: # stack.get_top() != match[ch]
return False
if stack.is_empty():
return True
else:
return False
print(brace_match('[{()}(){()}[]({}){}]'))
print(brace_match('[]}'))
队列
队列的实现
如下图所示,简单地用列表来实现,出队则front+1,入队rear+1,这样有个问题就是列表前面会存在大量地空位,造成内存的浪费,如图(d)所示。
队列的实现方式——环形队列
这里的%Maxsize
对队列长度取余就是为了使得指向11的最后一个位置加1后回到0的位置,得到环形队列。队满的时候rear没有指向front,目的是为了和空队列区分开来,所以队满时元素个数为Maxsize-1。
class Queue:
def __init__(self, size=100):
self.queue = [0 for _ in range(size)]
self.size = size
self.rear = 0 # 队尾指针
self.front = 0 # 队首指针
def push(self, element):
if not self.is_filled():
self.rear = (self.rear + 1) % self.size
self.queue[self.rear] = element
else:
raise IndexError("Queue is filled.")
def pop(self):
if not self.is_empty():
self.front = (self.front + 1) % self.size
return self.queue[self.front]
else:
raise IndexError("Queue is empty.")
# 判断队空
def is_empty(self):
return self.rear == self.front
# 判断队满
def is_filled(self):
return (self.rear + 1) % self.size == self.front
q = Queue(5)
for i in range(4):
q.push(i)
print(q.pop())
q.push(4)
双向队列
from collections import deque
q = deque([1,2,3,4,5], 5)
q.append(6) # 队尾进队
print(q.popleft()) # 队首出队
用于双向队列
q.appendleft(1) # 队首进队
q.pop() # 队尾出队
内置的双向队列队满后默认丢弃队首的元素,可以用来实现打印txt文件的最后n行信息。
from collections import deque
def tail(n):
with open('test.txt', 'r') as f:
q = deque(f, n)
return q
for line in tail(5):
print(line, end='')