我们首先关注如何基于最大堆实现最大优先队列:
优先队列(priority queue)是一种用来维护一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字(key)。
一个最大优先队列支持以下操作:
INSERT(S,x):把元素x插入集合S中,这一操作等价于S=S U {x}
MAXIMUM(S):返回S中具有最大关键字的元素。
EXTRACT-MAX(S):去掉并返回S中具有最大关键字的元素。
INCREASE-KEY(S,x,k):将元素x的关键字增加到k,这里假设k的值不小于x的原关键字值。
(1)MAXIMUM(S)
def heap_maximum(A):
return A[0];
import math
class heapsort:
def __init__(self,a_A):
self.list=a_A
self.heap_size = len(a_A)
def parent(self,i):
return math.floor((i-1)/2)
def left(self,i):
return 2*i+1
def right(self,i):
return 2*i+2
def max_heapify(self,A,i):
largest = i
key = A[i]
l = self.left(i)
r = self.right(i)
if l<len(A) and A[l] > A[largest]:
largest = 2*i+1
if r<len(A) and A[r] > A[largest]:
largest = 2*i+2
A[i]=A[largest]
A[largest]=key
if largest != i:
self.max_heapify(A,largest)
return A
def build_max_heap(self,A):
N = math.floor(len(A)/2)-1
for i in range(N,-1,-1):
A = self.max_heapify(A,i)
return A
运行结果:
>>> A=[4,1,3,2,16,9,10,14,8,7]
>>> p=heapsort(A)
>>> A=p.build_max_heap(A)
>>> A
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
>>> heap_maximum(A)
16
时间复杂度O(1)
(2)EXTRACT-MAX(S)def heap_extract_max(A):
if len(A)<1:
error("heap underflow")
max=A[0]
A[0]=A[len(A)-1]
heap_size=len(A)
p=heapsort(A,heap_size)
heap_size-=1
p.max_heapify(heap_size,A,1)
return max
import math
class heapsort:
def __init__(self,a_A,a_heap_size):
self.list=a_A
self.heap_size = a_heap_size
def parent(self,i):
return math.floor((i-1)/2)
def left(self,i):
return 2*i+1
def right(self,i):
return 2*i+2
def max_heapify(self,heap_size,A,i):
largest = i
key = A[i]
l = self.left(i)
r = self.right(i)
if l<heap_size and A[l] > A[largest]:
largest = 2*i+1
if r<heap_size and A[r] > A[largest]:
largest = 2*i+2
A[i]=A[largest]
A[largest]=key
if largest != i:
self.max_heapify(heap_size,A,largest)
return A
def build_max_heap(self,A):
N = math.floor(len(A)/2)-1
heap_size=len(A)
for i in range(N,-1,-1):
A = self.max_heapify(heap_size,A,i)
return A
def heapsort(self,A):
self.build_max_heap(A)
heap_size=len(A)
for i in range(len(A)-1,0,-1):
temp = A[0]
A[0] = A[i]
A[i] = temp
heap_size-=1
self.max_heapify(heap_size,A,0)
print(i,A)
运行:
>>> A=[4,1,3,2,16,9,10,14,8,7]
>>> p=heapsort(A,10)
>>> A=p.build_max_heap(A)
>>> heap_extract_max(A)
16
>>> A
[1, 14, 10, 8, 7, 9, 3, 2, 4, 1]
时间复杂度:O(lgn)
(3)INCREASE-KEY(S,x,k)
def heap_increase_key(A,i,key):
if key < A[i]:
error("new key is smaller than current key")
A[i]=key
heap_size=len(A)
p=heapsort(A,heap_size)
while i>0 and A[p.parent(i)]<A[i]:
t = A[i]
A[i]=A[p.parent(i)]
A[p.parent(i)]=t
i=p.parent(i)
import math
class heapsort:
def __init__(self,a_A,a_heap_size):
self.list=a_A
self.heap_size = a_heap_size
def parent(self,i):
return math.floor((i-1)/2)
def left(self,i):
return 2*i+1
def right(self,i):
return 2*i+2
def max_heapify(self,heap_size,A,i):
largest = i
key = A[i]
l = self.left(i)
r = self.right(i)
if l<heap_size and A[l] > A[largest]:
largest = 2*i+1
if r<heap_size and A[r] > A[largest]:
largest = 2*i+2
A[i]=A[largest]
A[largest]=key
if largest != i:
self.max_heapify(heap_size,A,largest)
return A
def build_max_heap(self,A):
N = math.floor(len(A)/2)-1
heap_size=len(A)
for i in range(N,-1,-1):
A = self.max_heapify(heap_size,A,i)
return A
def heapsort(self,A):
self.build_max_heap(A)
heap_size=len(A)
for i in range(len(A)-1,0,-1):
temp = A[0]
A[0] = A[i]
A[i] = temp
heap_size-=1
self.max_heapify(heap_size,A,0)
print(i,A)
运行结果:
>>> A=[4,1,3,2,16,9,10,14,8,7]
>>> p=heapsort(A,10)
>>> A=p.build_max_heap(A)
>>> A
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
>>> heap_increase_key(A,8,15)
>>> A
[16, 15, 10, 14, 7, 9, 3, 2, 8, 1]
时间复杂度:O(lgn) 关键字更新的结点到根结点的路径长度为lgn.
(4)INSERT(S,x)
def heap_increase_key(A,i,key):
if key < A[i]:
error("new key is smaller than current key")
A[i]=key
heap_size=len(A)
p=heapsort(A,heap_size)
while i>0 and A[p.parent(i)]<A[i]:
t = A[i]
A[i]=A[p.parent(i)]
A[p.parent(i)]=t
i=p.parent(i)
def max_heap_insert(A,key):
A.append(float("-inf"))
heap_increase_key(A,len(A)-1,key)
import math
class heapsort:
def __init__(self,a_A,a_heap_size):
self.list=a_A
self.heap_size = a_heap_size
def parent(self,i):
return math.floor((i-1)/2)
def left(self,i):
return 2*i+1
def right(self,i):
return 2*i+2
def max_heapify(self,heap_size,A,i):
largest = i
key = A[i]
l = self.left(i)
r = self.right(i)
if l<heap_size and A[l] > A[largest]:
largest = 2*i+1
if r<heap_size and A[r] > A[largest]:
largest = 2*i+2
A[i]=A[largest]
A[largest]=key
if largest != i:
self.max_heapify(heap_size,A,largest)
return A
def build_max_heap(self,A):
N = math.floor(len(A)/2)-1
heap_size=len(A)
for i in range(N,-1,-1):
A = self.max_heapify(heap_size,A,i)
return A
def heapsort(self,A):
self.build_max_heap(A)
heap_size=len(A)
for i in range(len(A)-1,0,-1):
temp = A[0]
A[0] = A[i]
A[i] = temp
heap_size-=1
self.max_heapify(heap_size,A,0)
print(i,A)
运行结果:
>>> A=[4,1,3,2,16,9,10,14,8,7]
>>> p=heapsort(A,10)
>>> A=p.build_max_heap(A)
>>> max_heap_insert(A,13)
>>> A
[16, 14, 10, 8, 13, 9, 3, 2, 4, 1, 7]
时间复杂度:O(lgn)