MIT6.006 lecture008

90 阅读1分钟

Priority Queue Interface:

  • Keep track of many items, quickly find the most important one.
  • Order items by key(like Set interface)
  • Usually optimized for max
  • Focus on insert and delete_max operations(build can repeatedly insert)
class Priority_Queue(A):
   def __init__(self, A):
       self.A = []

   def insert(self, x):
       self.A.append(x)

   def delete_max(self, A):
       if len(self.A) < 1:
           raise IndexError('pop from the empty array')
       self.A.pop()

   def sort(Queue, A):
       pq = Queue()
       for x in A:
           pq.insert(x)
       out = [pq.delete_max() for x in A]
       out.reverse()
       return out

Priority Queue Sort:

  • Priority queue translates into sorting algorithm

    • build(A) by insort items one by one
    • Repeatedlt delete_min to determine sorted order
  • T(running  time)=Tbuild+nTdeletemaxnTinsert+nTdeletemaxT(running \;time)=T_{build}+n T_{deletemax}\le n T_{insert}+n T_{deletemax}

Priority Queue: Array

  • store items in an unsorted dynamic array
  • insert(x) : append x to the end of the array
  • delete_max : find max item in O(n) time the swap it to the end of the array,and remove it

Insert is quick,delete_max is slow

class PQ_Array(Priority_Queue):
    def delete_max(self):
        # find the max item in the array
        n, A = len(self.A), self.A
        m = 0
        for i in range(1, n):
            if A[i] > A[m]: m = i
        A[m], A[n - 1] = A[n - 1], A[m]
        return super.delete_max()

Priority Queue : Sorted Array

  • store items in an sorted array
  • delete_max() : delete the last one in the array
  • insert(x) : append x to the array, then swap down to the sorted position in O(n) time

Delete_max is fast,but insert is low

class PQ_SortedArray(Priority_Queue):
    def insert(self, x):
        # maintain the order of the new array
        super().insert(x)
        i, A = len(A) - 1, self.A
        while i > 0 and (A[i].key < A[i - 1].key):
            A[i], A[i - 1] = A[i - 1], A[i]
            i -= 1

Array as Completed Binary Tree:

Except largest layer,every layer has 2i2^i items.And all nodes are left_aligned.

Implicit Completed Tree:

Completed binary tree can be implicit instead of storing pointers.

left(i)=2i+1right(i)=2i+2parent(i)=[i1/2]left(i) = 2i+1\\ right(i) = 2i+2\\ parent(i) = [i-1/2]
def parent(i):
    p = (i - 1) // 2
    return p if i > 0 else i

def left(i):
    l = 2 * i + 1
    return l if l < n else i

def right(i):
    r = 2 * i + 2
    return r if l < n else i


def max_heapify_up(A, n, c):
    p = parent(i)
    if A[p].key < A[c].key:
        A[p], A[c] = A[c], A[p]
        return max_heapify_up(A, n, p)

def max_heapify_down(A, n, p):
    l, r = left(i), right(i)
    c = l if A[l].key > A[r].key else r
    if A[c].key > A[p].key:
        A[p], A[c] = A[c], A[p]
    return max_heapify_down(A, n, c)

Binary heap:

  • Idea:: keep larger items higher in the tree,only locally
  • Property: Q[i] ≥ Q[j] for j ∈ {left(i),right(i)}
  • Claim: Q[i]Q[j]Q[i]\ge Q[j] for all nodes j in subtree(i)

Heap Insert:

  • append the new item in the end of the array
  • swap it with Max-Heap property
    • ifQ[parent]Q[i]Q[parent]\le Q[i] swap them,then recurve it untill the correct order
class PQ_Heap(Priority_Queue):
    def insert(self, x):
        super().insert(x)
        n, A = self.n, self.A
        max_heapify_up(A, n, n - 1)

Heap Delete_max:

  • Can only easily delete the last one in the array,and the max item is at the root
  • swap the item at root node (i==0) with the (n1)th(n-1)^{th} node
  • max_heapify_down(i): swap root with it's larger child recursively
class PQ_Heap(Priority_Queue):
    def delete_max(self):
        n, A = self.n, self.A
        A[n - 1], A[0] = A[0], A[n - 1]
        max_heapify_down(A, n, 0)
        return super().delete_max()

Linear build heap:

0n1(lgnlgi)=lgnnn!=θ(lgnnn(n/e)n)=O(n){\sum_{0}^{n-1}} (lg n-lgi)=lg{\frac{n^n}{n!}}=\theta {(lg {\frac{n^n}{{\sqrt{n}(n/e)^n}}})=O(n)}