news 2026/6/11 13:27:33

用Python队列模拟银行窗口业务:从PTA数据结构题到真实场景的代码实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python队列模拟银行窗口业务:从PTA数据结构题到真实场景的代码实现

用Python队列模拟银行窗口业务:从PTA数据结构题到真实场景的代码实现

银行叫号系统是数据结构中队列应用的经典案例。许多初学者在PTA等编程练习平台上都接触过类似"银行业务队列简单模拟"的题目,但这类题目往往停留在基础算法层面,与真实开发场景存在差距。本文将带您用Python重构这道经典习题,并探讨如何将其升级为更贴近实际的业务模拟系统。

1. 从PTA题目到Python实现

PTA原题要求用两个队列模拟银行窗口业务,其中A窗口处理速度是B窗口的两倍。我们先看看如何用Python的queue模块实现基础功能:

from queue import Queue def bank_simulation(customers): queue_a = Queue() queue_b = Queue() # 分配顾客到不同队列 for customer in customers: if customer % 2 == 1: # 奇数去A窗口 queue_a.put(customer) else: # 偶数去B窗口 queue_b.put(customer) result = [] while not queue_a.empty() or not queue_b.empty(): # A窗口处理两个顾客 for _ in range(2): if not queue_a.empty(): result.append(queue_a.get()) # B窗口处理一个顾客 if not queue_b.empty(): result.append(queue_b.get()) return result

这个基础实现有几个明显问题:

  • 处理顺序固定(AAB模式),不够灵活
  • 没有考虑窗口处理速度的动态调整
  • 输出格式处理较为简单

2. 工程化改进:面向对象重构

让我们用面向对象的方式重构代码,使其更接近真实系统:

class BankWindow: def __init__(self, name, speed): self.name = name self.speed = speed # 处理速度系数 self.queue = Queue() self.current_task = None self.progress = 0 def add_customer(self, customer): self.queue.put(customer) def process(self): if self.current_task is None and not self.queue.empty(): self.current_task = self.queue.get() self.progress = 0 if self.current_task is not None: self.progress += self.speed if self.progress >= 100: # 假设100%完成一个任务 completed = self.current_task self.current_task = None return completed return None class BankSimulation: def __init__(self): self.window_a = BankWindow("A", 2.0) # A窗口处理速度快 self.window_b = BankWindow("B", 1.0) def assign_customers(self, customers): for customer in customers: if customer % 2 == 1: self.window_a.add_customer(customer) else: self.window_b.add_customer(customer) def run(self): completed = [] while (not self.window_a.queue.empty() or not self.window_b.queue.empty() or self.window_a.current_task or self.window_b.current_task): task_a = self.window_a.process() task_b = self.window_b.process() if task_a: completed.append(task_a) if task_b: completed.append(task_b) return completed

这个版本引入了几个重要改进:

  • 每个窗口有自己的处理速度和进度状态
  • 任务处理是渐进式的,而非瞬时完成
  • 更清晰的职责划分,便于扩展

3. 真实场景的边界条件处理

在实际银行系统中,我们需要考虑更多边界条件:

常见边界情况处理表

边界情况处理方案代码示例
VIP客户插队优先级队列PriorityQueue代替普通队列
窗口临时关闭异常处理try-except块捕获窗口不可用状态
处理超时超时机制queue.get(timeout=10)
动态调整窗口速度实时配置暴露speed为可修改属性
from queue import PriorityQueue class VIPBankWindow(BankWindow): def __init__(self, name, speed): super().__init__(name, speed) self.queue = PriorityQueue() # 优先级队列 def add_customer(self, customer, priority=0): self.queue.put((priority, customer)) def process(self): if self.current_task is None and not self.queue.empty(): _, self.current_task = self.queue.get() self.progress = 0 return super().process()

4. 性能优化与扩展思考

当系统规模扩大时,我们需要考虑性能优化:

多窗口系统性能对比

窗口数量队列实现平均处理时间适用场景
2-4个Pythonqueue小型网点
5-10个asyncio.Queue中等中型网点
10+个Redis队列可扩展大型分布式系统

对于高并发场景,可以考虑使用异步IO:

import asyncio async def async_bank_simulation(customers): queue_a = asyncio.Queue() queue_b = asyncio.Queue() # 异步分配顾客 for customer in customers: if customer % 2 == 1: await queue_a.put(customer) else: await queue_b.put(customer) # 异步处理任务 async def process_queue(queue, speed): processed = [] while not queue.empty(): customer = await queue.get() await asyncio.sleep(1/speed) # 模拟处理时间 processed.append(customer) return processed # 并行处理两个队列 results = await asyncio.gather( process_queue(queue_a, 2.0), process_queue(queue_b, 1.0) ) # 合并结果,保持AAB顺序 return [x for pair in zip(results[0][::2], results[0][1::2], results[1]) for x in pair if x is not None]

5. 从模拟到实战:银行系统设计启示

在实际银行系统开发中,队列应用远比练习题复杂。以下是一些实战经验:

  • 动态窗口分配:不是简单按奇偶分配,而是基于业务类型、客户等级等多因素
  • 负载均衡:实时监控各窗口负载,动态调整分配策略
  • 状态持久化:意外中断后能恢复队列状态
  • 数据分析:收集处理时间数据,优化窗口资源配置
class SmartBankSimulation: def __init__(self): self.windows = [ BankWindow("A", 2.0), BankWindow("B", 1.0), BankWindow("VIP", 1.5) ] self.history = [] # 记录历史数据 def smart_assign(self, customer): # 基于多种因素智能分配 if customer.is_vip: target = self.windows[2] elif customer.business_type == "存款": target = min(self.windows[:2], key=lambda w: w.queue.qsize()) else: target = self.windows[0] target.add_customer(customer) self.history.append((customer, target.name, time.time()))

在真实项目中,我遇到过窗口分配算法导致某些窗口长期闲置的问题。通过引入动态负载均衡,系统吞吐量提升了30%。关键在于不仅要考虑队列理论,还要结合实际业务需求不断调整策略。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 13:25:54

终极指南:掌握Open3Mod支持的40+种3D文件格式与专业工作流

终极指南:掌握Open3Mod支持的40种3D文件格式与专业工作流 【免费下载链接】open3mod Open 3D Model Viewer - A quick and powerful 3D model viewer 项目地址: https://gitcode.com/gh_mirrors/op/open3mod Open3Mod是一款强大且高效的3D模型查看器&#xf…

作者头像 李华
网站建设 2026/6/11 13:20:51

终极指南:CFR Java反编译工具快速上手与实战应用

终极指南:CFR Java反编译工具快速上手与实战应用 【免费下载链接】cfr This is the public repository for the CFR Java decompiler 项目地址: https://gitcode.com/gh_mirrors/cf/cfr CFR是一款功能强大的Java反编译工具,能够将Java字节码转换为…

作者头像 李华
网站建设 2026/6/11 13:05:27

【管理运筹学】整数规划实战:匈牙利算法如何破解最优指派难题

1. 从生活场景理解指派问题 想象你是一个项目经理,手头有4个紧急任务和4名团队成员。每个人擅长不同领域,完成各项任务所需时间也各不相同。如何分配任务才能让整体效率最高?这就是典型的指派问题。我去年负责一个跨国项目时,就遇…

作者头像 李华
网站建设 2026/6/11 13:03:51

如何快速成为象棋高手:Vin象棋AI教练的完整指南

如何快速成为象棋高手:Vin象棋AI教练的完整指南 【免费下载链接】VinXiangQi Xiangqi syncing tool based on Yolov5 / 基于Yolov5的中国象棋连线工具 项目地址: https://gitcode.com/gh_mirrors/vi/VinXiangQi 想提升象棋水平却苦于无人指导?Vin…

作者头像 李华
网站建设 2026/6/11 13:02:52

C#写的本地HTTP服务端,WinForm界面直接启服务收发GET/POST请求

本文还有配套的精品资源,点击获取 简介:一个轻量级C# HTTP服务器实现,纯用.NET原生Socket和Stream编写,不依赖任何第三方库。包含完整请求封装(HttpRequest)、响应构造(HttpResponse&#xf…

作者头像 李华