数据结构与算法--数据结构性能分析、栈与队列

1.python数据结构性能分析

我们用到了timeit模块中的Timer类,测试一段python代码的执行速度。
Timer类有3个参数:

  1. stmt:接受测试的代码块语句
  2. setup:运行代码块所需的设置
  3. timeit函数:表示为Timer.timeit(number=10000),代表执行10000次该程序的平均耗时
from timeit import Timer
def addItem():
	alist = [ ]
	for i in range(1000):
		alist += [i]
	return alist

if __name__ == '__main__':
	# Timer类需要的参数,‘from __main__ import addItem’代表从主函数中插入addItem函数的设置
	t1 = Timer(stmt='addItem()',setup='from __main__ import addItem')
	time = t1.timeit(1000)
	print(time)

# pycharm执行结果:
# 0.11482795300071302

2.栈stack

栈和栈内元素好比乒乓球筒,遵循先进后出原则。

2.1 栈的应用

浏览器的后退与前进按钮
本质上就是把网页网址放入到一个栈中,第一个查看的网页存放在栈尾,点击返回按钮后,按照相反的顺序浏览刚才的页面。

2.2 栈的工作流程

class Stack():	# 创建一个空栈,无需参数
	# __init__ 是初始化方法,用来初始化实例后的对象stack,这样写self.items属性就可以作为一个变量
	def __init__(self):
		self.items = [ ]
	# 用于将一个新元素添加到栈顶
	def push(self,item):
		self.items.append(item)
	# 从栈中删除顶部项,无需传参,删除顶项
	def pop(self):
		return self.items.pop()
	# 判断栈是否为空,返回bool值
	def isEmpty(self):
		return self.items == [ ]
	# 返回栈中的item属性,返回整数
	def size(self):
		return len(self.items)
	# 从栈返回顶部项
	def peek(self):
		return 

alist = [1,2,3,4,5]
stack = Stack()
# 从alist中拿元素放入栈中
for item in alist:
	stack.push(item)
	print(stack.size())	
for i in range(len(alist)):
	print(stack.pop())
	

3.队列

队列就好比是一个高速公路隧道,特点是先进先出

2.1 队列的应用

应用场景
比如公司的打印机,各部门的打印需求都在一个队列中,第一个进入任务是先完成。

2.2 队列的工作流程

# 创建一个空的队列
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)

alist = [1,2,3,4,5]
q = Queue()
for item in alist:
	q.enqueue(item)
for i in range(len(alist)):
	print(q.dequeue())

2.3 案例:烫手的山芋

"""
烫手山芋游戏介绍:
6个孩子围城一个圈,排列顺序孩子们自己指定。第一个孩子手里有一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下一个孩子,依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一个孩子时结束,最后剩下的孩子获胜。请使用队列实现该游戏策略,排在第几个位置最终会获胜。

思路分析:
队列中有6个元素
一轮游戏是7秒.山芋被传递了几次(6)
"""

q = Queue()
# 一共有6个孩子,就是队列中的6个元素
kids = ['A', 'B', 'C', 'D', 'E', 'F']
# 往队列中添加6个元素,孩子进入队列
for kid in kids:
	q.enqueue(kid)
# 游戏开始:
# 只要队列中有超过1个孩子,就要进入新一轮游戏
while q.size() > 1:
	# 一轮游戏,按照队列中元素个数进行循环,(并不是循环1圈就删掉一个人)
	# 因为队列只能删除队首,无法随意位置删除,所以这个for循环实现了一个“模拟传递山芋的过程,并在传递后调整队列顺序,始终使拿山芋的人位于队首”。
	for i in range(len(kids)):
		kid = q.dequeue()	# dequeue(),队首移除,不需要参数并返回item
		q.enqueue(kid)		# 循环1圈,游戏未结束,队尾添加

	print(q.size())		# 每轮队列元素-1,打印队列长度
	print("这一轮退出游戏的是:",q.dequeue())
print("最终胜出者:",q.dequeue())

2.4 如何使用两个队列实现一个栈

分析:
栈的特性是先入后出(12345 -> 54321),队列的特性是先入先出

q1 = Queue()
q2 = Queue()
alist = [1,2,3,4,5]
for item in alist:
	q1.enqueue(item)	# q1 = [1,2,3,4,5]
while q1.size() > 0:
	for i in range(q1.size()-1):	# 循环4次,因为循环4次之后,q1=[5],直接dequeue取出就可以了,再走循环有点多余。
		# 从q1队首移除项并用item接收,加入q2队列队尾	从队首删,从队尾加。 q1 = [2,3,4,5] q2 = [1,]
		item = q1.dequeue()		# item = 1, item = 2, item = 3, item = 4,	q1 = [5,]
		q2.enqueue(item)		# q2 [1,]
	print(q1.dequeue())			# 此时5就取出来了,栈第一个取出来的元素就应该是5,没错
	q1,q2 = q2,q1				# 此时q2已经变成了原q1的格式,所以进行变量替换就可以继续加入循环,直至循环结束,输出54321
		

2.5 双端队列

同同列相比,有两个头部和尾部。可以在双端进行数据的插入和删除,提供了单数据结构中栈和队列的特性。

双端队列的应用:
回文检查。回文是一个字符串,读取首尾相同的字符,例如,radar toot madam。

"""
Deque() 创建一个空的新 deque。它不需要参数,并返回空的 deque。
addFront(item) 将一个新项添加到 deque 的首部。它需要 item 参数 并不返回任何内容。
addRear(item) 将一个新项添加到 deque 的尾部。它需要 item 参数并不返回任何内容。
removeFront() 从 deque 中删除首项。它不需要参数并返回 item。deque 被修改。
removeRear() 从 deque 中删除尾项。它不需要参数并返回 item。deque 被修改。
isEmpty() 测试 deque 是否为空。它不需要参数,并返回布尔值。
size() 返回 deque 中的项数。它不需要参数,并返回一个整数。
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值