堆的实现以及相关应用(堆排序、优先队列)——基于Python

堆实现

#------------------------------------------------------------------------------
#堆Heap
#------------------------------------------------------------------------------
import sys
class Heap():
    def __init__(self, A: list):
        self.A = A
        self.heap_size = len(A)
    #返回父节点索引
    def parent(self, i: int) -> int:
        return int((i-1)/2)
    #返回左孩子索引
    def left(self, i: int) -> int:
        return 2*i + 1
    #返回右孩子索引
    def right(self, i: int) -> int:
        return 2*i + 2
    #维护最大堆性质
    def max_heapify(self, i):
        l = self.left(i)
        r = self.right(i)
        if l < self.heap_size and self.A[l] > self.A[i]:
            largest = l
        else:
            largest = i
        if r < self.heap_size and self.A[r] > self.A[largest]:
            largest = r
        if largest != i:
            self.A[i], self.A[largest] = self.A[largest], self.A[i]
            self.max_heapify(largest)
    #维护最小堆性质
    def min_heapify(self, i):
        l = self.left(i)
        r = self.right(i)
        if l < self.heap_size and self.A[l] < self.A[i]:
            smallest = l
        else:
            smallest = i
        if r < self.heap_size and self.A[r] < self.A[smallest]:
            smallest = r
        if smallest != i:
            self.A[i], self.A[smallest] = self.A[smallest], self.A[i]
            self.min_heapify(smallest)
    #创建最大堆
    def build_max_heap(self):
        #不除以2也可以,为减少计算量
        for i in range(int(len(self.A)/2)-1, -1, -1):
            self.max_heapify(i)
    #创建最小堆
    def build_min_heap(self):
        for i in range(int(len(self.A)/2)-1, -1, -1):
            self.min_heapify(i)
    #堆排序(升序)
    def heap_sort(self):
        self.build_max_heap()
        for i in range(len(self.A)-1, 0 ,-1):
            self.A[0], self.A[i] = self.A[i], self.A[0]
            self.heap_size -= 1
            self.max_heapify(0)
# =============================================================================
# A = [4,1,3,2,16,9,10,14,8,7]
# heap = Heap(A)
# heap.heap_sort()
# =============================================================================

最大优先队列

''''最大优先队列'''
class HeapMaxPriorityQueue():
    def __init__(self, A):
        self.A = A
        self.heap = Heap(A)
        #创建最大堆
        self.heap.build_max_heap()
    #返回A中具有最大键字的元素
    def heap_maximun(self):
        return A[0]
    #去掉并返回A中具有最大键字的元素
    def heap_extract_max(self):
        if self.heap.heap_size < 1:
            sys.exit('heap underflow')
        Max = self.A[0]
        self.A[0] = self.A[self.heap.heap_size - 1]
        self.heap.heap_size -= 1
        self.A.pop()
        self.heap.max_heapify(0)
        return Max
    #将元素i的值增加到k
    def heap_increase_key(self, i, key):
        if key < self.A[i]:
            sys.exit('new key is smaller than current key!!!')
        self.A[i] = key
        while i > 0 and self.A[self.heap.parent(i)] < A[i]:
            self.A[i], self.A[self.heap.parent(i)] = \
                self.A[self.heap.parent(i)],self.A[i]
            i = self.heap.parent(i)
    #插入新元素
    def heap_max_insert(self, key):
        self.heap.heap_size += 1
        self.A.append(-float('inf'))
        #将末尾元素键值增加到key
        self.heap_increase_key(self.heap.heap_size - 1, key)
        
# =============================================================================
# A = [4,1,3,2,16,9,10,14,8,7]
# MaxPriorityQueue =   HeapMaxPriorityQueue(A) 
# print(MaxPriorityQueue.heap_extract_max() ) 
# # MaxPriorityQueue.heap_max_insert(13)    
# =============================================================================

最小优先队列

''''最小优先队列'''
class HeapMinPriorityQueue():
    def __init__(self, A):
        self.A = A
        self.heap = Heap(A)
        #创建最小堆
        self.heap.build_min_heap()
    #返回A中具有最大键字的元素
    def heap_minimun(self):
        return A[0]
    #去掉并返回A中具有最大键字的元素
    def heap_extract_min(self):
        if self.heap.heap_size < 1:
            sys.exit('heap underflow')
        Min = self.A[0]
        self.A[0] = self.A[self.heap.heap_size - 1]
        self.heap.heap_size -= 1
        self.A.pop()
        self.heap.min_heapify(0)
        
        return Min
    #将元素i的值减小到k
    def heap_increase_key(self, i, key):
        if key > self.A[i]:
            sys.exit('new key is bigger than current key!!!')
        self.A[i] = key
        while i > 0 and self.A[self.heap.parent(i)] > A[i]:
            self.A[i], self.A[self.heap.parent(i)] = \
                self.A[self.heap.parent(i)],self.A[i]
            i = self.heap.parent(i)
    #插入新元素
    def heap_min_insert(self, key):
        self.heap.heap_size += 1
        self.A.append(float('inf'))
        #将末尾元素键值增加到key
        self.heap_increase_key(self.heap.heap_size - 1, key)

最小优先队列可以使用Python自带的'heapq'完成

import heapq     
A = [4,1,3,2,16,9,10,14,8,7]
heapq.heapify(A)
heapq.heappop(A)
heapq.heappush(A, 0.4) 

heapq模块提供了如下几个函数:

  • heapq.heappush(heap, item) : 把item添加到heap中(heap是一个列表)
  • heapq.heappop(heap) : 把堆顶元素弹出,返回的就是堆顶(优先级最高的元素)
  • heapq.heappushpop(heap, item) :先把item加入到堆中,然后再pop,比heappush()再heappop()要快得多
  • heapq.heapreplace(heap, item) :先pop,然后再把item加入到堆中,比heappop()再heappush()要快得多
  • heapq.heapify(x) :将列表x进行堆调整,默认返回的是小顶堆
  • heapq.merge(*iterables) :将多个列表合并,并进行堆调整,返回的是合并后的列表的迭代器
  • heapq.nlargest(n, iterable, key=None) 返回最大的n个元素(Top-K问题)
  • heapq.nsmallest(n, iterable, key=None) 返回最小的n个元素(Top-K问题)

note

  • item可以为各种形式,比如可以为元组,这样在进行堆调整是,先以元组第一个元素为基准,如果第一个相等,再以第二个为基准,依次类推
  • 使用堆操作,在一个有n个元素的堆中添加一个元素或者删除一个元素的时间复杂度均为O(logn)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值