【数据结构Python描述】优先级队列描述“银行VIP客户插队办理业务”及“被插队客户愤而离去”的模型实现

【数据结构Python描述】优先级队列简介及Python手工实现给出了优先级队列ADT的典型方法,这些方法对于如排序等常见应用已经足够,但在如下述的一些场景中,仍需要对优先级队列的ADT所包含的方法进行扩充:

  • 一位土豪正在某银行排队办理业务,在等待过程中土豪突然发现自己是该行的VIP,在告知工作人员后,该土豪的排队优先级被提至最高
  • 本来排在土豪前面准备存钱的普通客户见状便找工作人员理论,后者告知前者土豪是VIP,根据该行规定有权享受这样的待遇,普通客户见沟通无果便要求删除自己取的号,然后愤而离去将存款存到了隔壁银行。

如果你想要直接体验实现上述情景的代码,请直接跳至第四部分。

一、支持插队模型的优先级队列

队列ADT扩充

分别对应上述两种情况,还需要在一般优先级队列ADT的基础上对其进行扩充,以增加下列两个方法:

  • update(item, key, value):将item中的keyvalue实例属性进行更新替换;
  • remove(item):从优先级队列中删除item并返回(key, value)

队列记录描述

需要注意的是,由于update()remove()方法的执行都有赖于先在优先级队列中找到对应的item,为了避免需要遍历存储所有item列表,这里需要对item实例所属的_Item进行升级,即为在其键值对(key, value)的基础上增添该条记录在列表中的索引idx,即一个item对象具有三个实例属性(key, value, idx)

方法理论步骤

为了使得后续给出的上述两个新增方法的实现更容易理解,下面通过具体案例先从理论上分析每一个方法操作的步骤。

首先,假设分别通过以下两种形式给出一个已有的优先级队列的所有记录集合:

在这里插入图片描述

update(item, key, value)

如果cursor = Item(9, 'F', 4),则执行q.update(cursor, 1, 'F')的具体步骤如下:

  • 首先,如图(a)和(b)所示,将cursor所引用记录(9, 'F', 4)中的键修改为1(也可以此时同时修改值'F'为任意对象)。

在这里插入图片描述

  • 其次,如图(c)和(d)所示,为确保优先级队列某记录的键值修改后,底层的完全二叉树仍然是一个,需要进行结点间记录的交换;

在这里插入图片描述

  • 然后,如图(e)和(f)所示,为了使得交换后的记录的idx域都如实反应该条记录在列表中的索引,需要分别修改两条记录的idx

在这里插入图片描述

  • 接着,重复图©、(d)、(e)、(f)的步骤直到完全二叉树满足堆序性质且每条(key, value, idx)记录的idx域均如实反应该条记录在列表的位置。

在这里插入图片描述

remove(item)

下面还是以本节一开始的案例分析该方法操作的理论步骤,即如果item= Item(9, 'F', 4),则执行q.remove(item)的具体步骤如下:

  • 首先,如图(a)和(b)所示,将要删除的记录交换至列表尾部(即完全二叉树最底层最右侧结点处);

在这里插入图片描述

  • 其次,如图©和(d)所示,类似上述分析update()方法,交换记录后需要修改记录的idx域;

在这里插入图片描述

  • 然后,如图(e)和(f)所示,删除列表尾部元素,实际上只要调用列表的pop()方法即可;

在这里插入图片描述

  • 最后,得到如图(g)和(h)所示的结果。实际上,如果上述(e)和(f)所示步骤结束后完全二叉树不满足堆序性质,则还需像分析update()方法时一样,重复图©、(d)、(e)、(f)的步骤。

在这里插入图片描述

二、支持插队模型的优先级队列实现

基于上述分析,本节将通过继承【数据结构Python描述】树堆(heap)简介和Python手工实现及使用树堆实现优先级队列中实现的HeapPriorityQueue来实现支持插队模型的优先级队列AdaptablePriorityQueue

Item

首先,需要对描述优先级队列中每一条记录的_Item进行如下所示的升级

from heap_priority_queue import HeapPriorityQueue


class Item(HeapPriorityQueue._Item):
    """用于保存优先级队列每一条记录的键、值以及键值在列表中索引的类"""
    def __init__(self, key, value, idx):
        super().__init__(key, value)
        self.idx= idx

也就是说,后续优先级队列底层的列表保存的是一系列Item实例,每一个实例均保存了keyvalue以及当前实例在列表中的索引idx,对于用户向优先级队列中成功插入的每一对(key, value),都会得到一个Item实例的引用,如图分析update()方法时提到中的cursor

_swap(i, j)

HeapPriorityQueue中实现过了该方法,此处需重写该方法使得(key, value, idx)形式的记录的idx域如实反应该记录当前在列表中的位置:

def _swap(self, i, j):
    """重写父类方法"""
    super()._swap(i, j)
    self._data[i].idx = i
    self._data[j].idx 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值