如何检测调用父类Heap方法的子类类型,适配MinHeap与MaxHeap?
实现方案
不用硬检测子类类型,也不用在子类重复写heapify、heappop的公共逻辑,用钩子方法的设计就能实现需求,这也是面向对象里复用代码的标准做法,比判断类型更易维护。
方案1:推荐写法(钩子方法实现)
步骤1:改造Heap基类,预留比较逻辑钩子
基类默认实现小顶堆的比较逻辑,对应你要求的「基类默认按MinHeap逻辑实现」的规则:
from typing import List class Heap: def __init__(self, array: List[int]) -> None: self.elements = array self.size = len(array) # Number of elements in heap self.build_heap() # 比较钩子:返回True代表第一个参数应该比第二个参数更靠近堆顶 def _compare(self, a: int, b: int) -> bool: # 基类默认小顶堆逻辑:更小的数排在堆顶 return a < b def heapify(self, idx: int) -> None: left = 2 * idx + 1 right = 2 * idx + 2 target = idx # 所有比较逻辑调用钩子方法,不写死大小判断 if left < self.size and self._compare(self.elements[left], self.elements[target]): target = left if right < self.size and self._compare(self.elements[right], self.elements[target]): target = right if target != idx: self.elements[idx], self.elements[target] = self.elements[target], self.elements[idx] self.heapify(target) def build_heap(self) -> None: for i in range(self.size // 2 - 1, -1, -1): self.heapify(i) def heappop(self) -> int: if self.size == 0: raise IndexError("Heap is empty") top = self.elements[0] self.elements[0] = self.elements[self.size - 1] self.size -= 1 self.heapify(0) self.elements.pop() return top
步骤2:子类仅重写比较钩子即可,无需重写其他公共方法
class MinHeap(Heap): # 直接继承基类的小顶堆比较逻辑,不需要额外写代码 pass class MaxHeap(Heap): # 仅重写比较逻辑,heapify、heappop、build_heap全部复用基类代码 def _compare(self, a: int, b: int) -> bool: return a > b
方案2:判断子类类型实现(符合你的预期目标,不推荐生产用)
如果一定要通过判断子类类型实现逻辑分支,可以用isinstance检测当前实例的类型:
def heapify(self, idx: int) -> None: left = 2 * idx + 1 right = 2 * idx + 2 target = idx # 硬编码判断子类类型切换比较逻辑 if isinstance(self, MaxHeap): compare_func = lambda a,b: a > b else: compare_func = lambda a,b: a < b if left < self.size and compare_func(self.elements[left], self.elements[target]): target = left if right < self.size and compare_func(self.elements[right], self.elements[target]): target = right if target != idx: self.elements[idx], self.elements[target] = self.elements[target], self.elements[idx] self.heapify(target)
注意:该方法扩展性差,后续新增其他规则的堆时需要不断修改基类判断逻辑,违反开闭原则,仅建议临时满足作业要求使用。
内容的提问来源于stack exchange,提问作者Logan
相关产品推荐
相关产品推荐

