Click to Visit Homepage : zzyzz.top


Algorithms - Priority Queue - 优先队列

Priority queue - 优先队列

相关概念
    Priority queue优先队列是一种用来维护由一组元素构成的集合S的数据结构,
    其中的每一种元素都有一个相关的值,称为关键字(key)。
    一个最大有限队列支持一下操作:
        insert(S,x):把元素x插入到集合S中.
        maximum(S):返回集合S中具有最大关键字的元素.
        extract_max(S):去掉并返回S中具有最大关键字的元素
        increase_key(S,x,k):将集合S中的元素x的关键字值增加到k,这里假设k的值不小于x元素原来的关键字的值
    
    最大优先队列的应用有很多,其中一个就是在共享计算机系统的作业调度.最大优先队列记录将要执行的各个作业以及他们之间的相对优先级. 当一个作业完成或者被中断后,调度器调用extract_max(S),从所有作业中,选优具有最高优先级的作业来执行. 在任何时候,调度器都可以调用insert把一个新的作业加入到队列中.
    
    相应地,最小优先队列支持的操作包括:insert,minimum,extract_min和decrease_key.最小优先队列可以被用于基于事件驱动的模拟器.队列中保存要模拟的事件,每个事件都有一个发生时间作为其关键字.
    
    事件必须按照发生的时间顺序进行模拟,因为某一事件的模拟结果可能会触发其他事件的模拟. 在每一步,模拟程序调用extract_min来获得下一个要模拟的事件.当一个新事件产生时,模拟器通过调用insert将其插入到最小优先级队列中.
    
    优先队列可以用堆来实现.对一个像作业调度或时间驱动模拟器这样的程序来说,优先队列的元素对应着应用程序中的对象.
Python programming

# 优先队列是基于最大堆实现的. 
import heap_sorting    # heap_sorting 模块代码位于: https://www.cnblogs.com/zzyzz/p/12869256.html

def heap_maximum(A):
    return A[0]

def heap_extract_max(A, heap_size):    # heap_size 是堆的一个属性, 这里通过一个函数参数的形式实现.
    if heap_size < 1:
        print('error - heap underflow')
        return False
    max = A.pop(0)
    heap_size -= 1
    heap_sorting.max_heapify(A,1,heap_size)
    return max

if __name__ == '__main__':
    A = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
    print('Before', A)
    heap_extract_max(A, 10)
    print('After', A)

结果打印:
   Before [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
   After [14, 10, 8, 7, 9, 3, 2, 4, 1]
def heap_increase_key(A, i, key):
    if key < A[i-1]:
        print('error - new key is smaller than current key')
        return False
    # 最大堆 A 中的第 i 个元素 A[i-1] 首先被替换成待插入的元素 key
    A[i-1] = key

    # 新插入的元素会不断地与其父结点进行比较, 如果当前元素 key 比较大, 则与其父结点进行交换, 更新 i 的值后继续比较. 直到当前元素 key 小于其父结点的时候终止循环.
    while i > 1 and A[heap_sorting.parent(i)-1] < A[i-1]:
        print(A[heap_sorting.parent(i) - 1], A[i - 1])
        A[i-1], A[heap_sorting.parent(i)-1] = A[heap_sorting.parent(i)-1], A[i-1]
        i = heap_sorting.parent(i)
        print('i',i)
        print('A',A)

if __name__ == '__main__':
    A = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
    print('Before', A)
    heap_increase_key(A,9,15)   # 将 15 插入到最大堆 A 中. 然后加工新的数组为新的最大堆.
    print('After', A)

结果打印: Before [
16, 14, 10, 8, 7, 9, 3, 2, 4, 1] 8 15 # 第一次循环的 parent 和 key i 4 # parent < key, 更新 i A [16, 14, 10, 15, 7, 9, 3, 2, 8, 1] # 第一次循环后得到的新数组 14 15 # 第二次循环的 parent 和 key i 2 # parent < key, 更新 i A [16, 15, 10, 14, 7, 9, 3, 2, 8, 1] # # 第二次循环后得到的新数组 After [16, 15, 10, 14, 7, 9, 3, 2, 8, 1] # 循环退出后的得到新数组即为新的最大堆

def max_heap_insert(A, key, heap_size):
    heap_size += 1
    A.insert(heap_size-1, -float('inf'))
    print(A)
    heap_increase_key(A, heap_size, key)

if __name__ == '__main__':
    A = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
    print('Before', A)
    max_heap_insert(A,13,10)
    print('After', A)

结果打印:
Before [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1, -inf]     # 先在对应的位置上设置一个 sentinel
7 13                                                  # parent < key
i 5                                                     # 交换 parent 和 key 后更新 i
A [16, 14, 10, 8, 13, 9, 3, 2, 4, 1, 7]    # 交换后新的数组
After [16, 14, 10, 8, 13, 9, 3, 2, 4, 1, 7]    # 循环退出后的结果

 

Reference,

  1. Introduction to algorithms

 

posted @ 2020-05-12 13:20  zzYzz  阅读(226)  评论(0编辑  收藏  举报


Click to Visit Homepage : zzyzz.top