算法:对问题进行处理且求解的一种思路或者思想
时间复杂度:量化算法执行的操作执行步骤的数量,最重要的项,采用大O记法
数据结构:对于基本数据的组织方式
python数据结构性能分析:
from timeit import Timer
def test01():
alist = []
for i in range(1000):
alist = [i]
return alist
def test02():
alist = []
for i in range(1000):
alist.appned(i)
return alist
def test03():
return [i for i in range(1000)]
def test04():
alist = list(range(1000))
return alist
if __name__=="__main__":
timer1 = Timer("test01()",'from __main__ import test01')
t1 = timer1.timeit(10000)
timer2 = Timer("test02",'from __main__ import test02')
t2 = timer2.timeit(10000)
timer3 = Timer("test03",'from __main__ import test03')
t3 = timer3.timeit(10000)
timer4 = Timer("test04",'from __main__ import test04')
t4 = timer4.timeit(10000)
print(t1,t2,t3,t4)
特性:先进后出的数据结构
# 自定义一个栈类
class Stack():
def __init__(self):
self.items = []
def enqueue(self,item): # 入栈
self.items.append(item)
def dequeue(self): # 出栈
return self.items.pop()
def peek(self): # 返回栈的顶部项
return len(self.items)-1
def isEmpty(self): # 判断是否为空
return self.items == []
def size(self): # 判断栈的元素个数
return len(self.items)
特性:先进先出
案例:烫手的山芋
游戏介绍:6个孩子围成一个圈,排列顺序自己指定,第一个孩子手里有一个山芋,需要在计时器1秒后传递给下一个孩子,依次类推,规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏,该游戏直到只剩下一个孩子时结束,使用队列实现该游戏策略,排在第几个位置最终会获胜。
#! -*- encode: utf-8 -*-
# 准则:手里有山芋的孩子永远排在队列的头部
# 自定义一个队列类
class Queue():
def __init__(self):
self.items = []
def enqueue(self,item): # 入队列
self.items.insert(0,item)
def dequeue(self): # 出队列
return self.items.pop()
def isEmpty(self): # 判断是否为空
return self.items == []
def size(self): # 判断元素个数
return len(self.items)
kids = ["A","B","C","D","E","F"]
queue = Queue()
for kid in kids:
queue.enqueue(kid) # A对尾 F队尾
while queue.size() > 1:
for i in range(6): # 传递次数
kid = queue.dequeue() # 让队头元素先出队列
queue.enqueue(kid) # 再入队列,保持拿芋头的人在队头
queue.dequeue() # 一次计时结束,删除队头的人
print("获胜的选手是:",queue.dequeue())
特性:有两个头部和尾部,可以在双端进行数据的插入和删除,提供了单数据结构中栈和队列的特性
案例:实现回文检查
#! -*- encode: utf-8 -*-
# 自定义双端队列类
class Deque():
def __init__(self):
self.items = []
def addFront(self,item): # 首部添加元素
self.items.insert(0,item)
def addRear(self,item): # 尾部添加元素
self.items.append(item)
def removeFront(self): # 删除首部元素
return self.items.pop()
def removeRear(self): # 删除尾部元素
return self.items.pop(0)
def isEmpty(self): # 判断是否为空
return self.items == []
def size(self): # 判断元素个数
return len(self.items)
def isHuiWen(s):
deque = Deque()
for i in str(s):
deque.addRear(i)
while deque.size() > 0:
if deque.removeFront() != deque.removeRear():
res = False
break
else:
res = True
return res
print(isHuiWen(12345321))
面试题:如何用两个队列形成一个栈
# 自定义一个队列类
class Queue():
def __init__(self):
self.items = []
def enqueue(self,item): # 入队列
self.items.insert(0,item)
def dequeue(self): # 出队列
return self.items.pop()
def isEmpty(self): # 判断是否为空
return self.items == []
def size(self): # 判断元素个数
return len(self.items)
def travel(self):
for item in self.items:
print(item)
alist = ["1","2","3","4","5"]
queue = Queue()
for i in alist:
queue.enqueue(i)
def toStack(queue):
queue2 = Queue()
while queue.size() > 0:
while True:
item = queue.dequeue()
if queue.size() == 0:
print(item)
break
queue2.enqueue(item)
if queue.size() <= 1:
print(queue.dequeue())
break
queue,queue2 = queue2,queue
toStack(queue)
集合中存储的元素是有顺序的,顺序表的结构分为单数据类型和多数据类型
列表和元组属于多数据类型的顺序表 一个整型占据的内存占四个字节
单数据类型:内存空间连续开辟,数据类型统一
多数据类型顺序表:内存非连续开辟,同时会开辟一个单独的内存空间来存放非连续内存空间的地址
弊端:顺序表的结构需要预先知道数据大小来申请连续的存储空间,而在扩充时又需要进行数据的搬迁
一种常见的线性表,不像顺序表一样连续存储数据,而是每一个结点(数据存储单元)里存放下一个结点的信息(地址)
相对于顺序表,链表结构可以充分利用计算机内存空间,实现灵活的动态内存管理且进行扩充时不需要进行数据搬迁
class Node():
def __init__(self,item):
self.item = item
self.next = None
class Link():
def __init__(self):
# 构造出一个空的列表
# 且_head只能为空或者第一个结点的地址
self._head = None
# 向链表的头部添加一个结点
def add(self,item):
# 创建一个新的结点
node = Node(item)
# 先把之前数据的地址传递到新插入数据的next属性中
node.next = self._head
# 将新数据的地址赋值给_head属性,这样就成功插入到了头部
self._head = node
# 链表的遍历
def travel(self):
# _head 在链表创建好后一定是不可变的,一旦变化,链表随之改变
cur = self._head
while cur: # 当cur为None时,结束遍历
print(cur.item)
cur = cur.next
# 链表的长度
def size(self):
cur = self._head
count = 0
while cur:
count += 1
cur = cur.next
return count
# 向链表的尾部添加
def append(self,item):
node = Node(item)
# 需要做一个链表为空的判断
if self._head == None:
self._head = node
return
cur = self._head
# 判断前一个是否为末端,如果不是则继续往前取值
while cur.next:
cur = cur.next
cur.next = node
# 查找
def search(self,item):
cur = self._head
while cur:
if cur.item = item:
find = True
break
else:
cur = cur.next
find = False
return find
# 定向插入
def insert(self,pos,item):
if pos == 0 or pos > self.size():
print('插入的位置有误')
return
node = Node(item)
pre = None
cur = self._head
for i in range(pos):
pre = cur
cur = cur.next
pre.next = node
node.text = cur
# 定向删除
def remove(self,item):
cur = self._head
pre = None
while cur :
if cur.item == item:
pre.next = cr.next
return
pre = cur
cur = cur.next
# 链表倒置
def reverse(self):
cur = self._head
pre = None
nex = cur.next
if cur == None:
print('列表为空')
while cur:
cur.next = pre
pre = cur
cur = nex
if cur:
nex = cur.next
self._head = pre
return
根节点
叶子节点:左叶子结点 右叶子结点
数的层级/数的高度
class Node():
def __init__(self,item):
self.item = item
self.left = None
self.right = None
class Tree():
def __init__(self):
self.root = None
def addNode(self,item):
node = Node(item)
# 如果插入第一个结点的情况
if self.root == None:
self.root = node
return
cur = self.root
q = [cur] # 列表元素使我们遍历判断的结点
while q:
nd = q.pop(0)
if nd.left == None:
nd.left = node
return
else:
q.append(nd.left)
if nd.right == None:
nd.right = node
return
else:
q.append(nd.right)
def travel(self):
cur = self.root
q = [cur]
while q:
nd = q.pop(0)
print(nd.item)
if nd.left:
q.append(nd.left)
if nd.right:
q.append(nd.right)
# 深度遍历:前序
def forward(self,root):
if root == None:
return
print(root.item)
self.forward(root.left)
self.forward(root.right)
# 深度遍历:中序
def middle(self,root):
if root == None:
return
self.middle(root.left)
print(root.item)
self.middle(root.right)
# 深度遍历:后序
def back(self,root):
if root == None:
return
self.back(root.left)
self.back(root.right)
print(root.item)
广度优先遍历:一层一层对结点进行遍历
深度优先遍历:
前序:根左右 1 2 4 5 3 6 7
中序:左根右 4 2 5 1 6 3 7
后序:左右根 4 5 2 6 7 3 1
乱序数据的插入的时候,需要遵从一个准则:
插入的第一个数值作为树的根节点
乱序插入的数值,如果比根节点小,插入根节点的左侧,否则插入到根节点的右侧
# 排序二叉树
class Node():
def __init__(self,item):
self.item = item
self.left = None
self.right = None
class SortTree():
def __init__(self):
self.root = None
def add(self,item):
node = Node(item)
cur = self.root
if self.root == None:
self.root = node
return
while cur:
# 右侧插入
if item > cur.item:
if cur.right == None:
cur.right = node
break
else:
cur = cur.right
else: # 左侧插入
if cur.left == None:
cur.left = node
break
else:
cur = cur.left
# 深度遍历:中序
def middle(self,root):
if root == None:
return
self.middle(root.left)
print(root.item)
self.middle(root.right)