数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单的说就是设计数据以何种方式组织并存储在计算机中。
列表、集合和字典等都是一种数据结构。
数据结构按照其逻辑结构可以分为:线性结构(一对一)、树结构(一对多)、图结构(多对多)
下面是几种常用的数据机构:
列表
列表是一个常用的数据结构,和C的数组很相似,但是又有所不同。
不同点:
1、数组元素类型要相同,而python的列表则可以存储各种类型的数据,因为数组是存放的内容,有着固定的字节长度,而python存放的是内容的地址,所以不需要考虑元素存储大小的问题;
2、数组的长度固定,而列表可以自由创建。
列表寻找下标的时间复杂度为: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
def is_empty(self):
return len(self.stack) == 0 # 最后是一个判断语句,为空时是True,不为空时是False
# 主函数
stack = Stack()
stack.push(1)
stack.push(2)
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 # 最后是一个判断语句,为空时是True,不为空时是False
def brace_match(s):
match = {')':'(','}':'{',']':'['}
stack = Stack()
for ch in s:
if ch in {'(','[','{'}:
stack.push(ch)
else:
if stack.is_empty():
return False
elif stack.get_top() == match[ch]:
stack.pop()
else:
return False
if stack.is_empty():
return True
else:
return False
a = '{[[](){}]}'
b = '{[[](){}}'
print(brace_match(a))
print(brace_match(b))
队列
队列是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。插入动作称为进队或入队,进行插入的一端称为队尾(rear),插入动作称为进队或入队;进行删除的一端称为队头(front),删除动作称为出队。队列的属性:先进先出。
队列的实现方式:环形队列。
下图就是环形队列:
当队尾指针rear == maxsize-1时,也就是指向最大下标的位置,再前进一位就回到0。
队首指针前进1:front = (front + 1) % maxsize
队尾指针前进1:rear = (rear + 1) % maxsize
对空的条件:rear == front
队满条件:(rear+1)% maxsize == front (队列总是留着一个空位,以此来判断队满和队空)
代码如下:
# 环形队列
# 可以理解为队首总是指向为空,虽然实际上是会有值,但是我们用不到,可以忽略,所以我们能用的队列长度=我们设定的大小-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 # 队尾加1
self.queue[self.rear] = element
else:
raise IndexError("Queue is failed.")
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(3)
q.push(1)
q.push(2)
q.pop()
q.push(3)
print(q.pop())