python手写实现堆数据结构

1.初始化

def __init__(self,desc=False):
    """
    初始化,默认创建一个小顶堆
    """
    self.heap = []
    self.desc = desc

2.堆的大小

@property
def size(self):
    return len(self.heap)

3.返回堆顶元素

def top(self):
    if self.size:
        return self.heap[0]
    return None

4.添加元素

def push(self,item):
    """
    添加元素
    第一步,把元素加入到数组末尾
    第二步,把末尾元素向上调整
    """
    self.heap.append(item)
    self._sift_up(self.size-1)

5.弹出堆顶元素

def pop(self):
    """
    弹出堆顶
    第一步,记录堆顶元素的值
    第二步,交换堆顶元素与末尾元素
    第三步,删除数组末尾元素
    第四步,新的堆顶元素向下调整
    第五步,返回答案
    """
    item = self.heap[0]
    self._swap(0,self.size-1)
    self.heap.pop()
    self._sift_down(0)
    return item

6.判断两个元素的大小关系,这里有个小trick

return left if True else right #条件为True则总是返回left
return left if False else right #条件为False则总是返回right
def _smaller(self,lhs,rhs):
    return lhs > rhs if self.desc else lhs < rhs

7.向上调整

def _sift_up(self,index):
    """
    向上调整
    如果父节点和当前节点满足交换的关系
    (对于小顶堆是父节点元素更大,对于大顶堆是父节点更小),
    则持续将当前节点向上调整
    """
    while index:
        parent = (index-1) // 2
        
        if self._smaller(self.heap[parent],self.heap[index]):
            break
            
        self._swap(parent,index)
        index = parent

8.向下调整

def _sift_down(self,index):
    """
    向下调整
    如果子节点和当前节点满足交换的关系
    (对于小顶堆是子节点元素更小,对于大顶堆是子节点更大),
    则持续将当前节点向下调整
    """
    # 若存在子节点
    while index*2+1 < self.size:
        smallest = index
        left = index*2+1
        right = index*2+2
        
        if self._smaller(self.heap[left],self.heap[smallest]):
            smallest = left
            
        if right < self.size and self._smaller(self.heap[right],self.heap[smallest]):
            smallest = right
            
        if smallest == index:
            break

        self._swap(index,smallest)
        index = smallest

9.交换两个元素

def _swap(self,i,j):
    self.heap[i],self.heap[j] = self.heap[j],self.heap[i]

完整代码

class Heap:
    def __init__(self,desc=False):
        """
        初始化,默认创建一个小顶堆
        """
        self.heap = []
        self.desc = desc
    
    @property
    def size(self):
        return len(self.heap)
    
    def top(self):
        if self.size:
            return self.heap[0]
        return None
    
    def push(self,item):
        """
        添加元素
        第一步,把元素加入到数组末尾
        第二步,把末尾元素向上调整
        """
        self.heap.append(item)
        self._sift_up(self.size-1)
    
    def pop(self):
        """
        弹出堆顶
        第一步,记录堆顶元素的值
        第二步,交换堆顶元素与末尾元素
        第三步,删除数组末尾元素
        第四步,新的堆顶元素向下调整
        第五步,返回答案
        """
        item = self.heap[0]
        self._swap(0,self.size-1)
        self.heap.pop()
        self._sift_down(0)
        return item
    
    def _smaller(self,lhs,rhs):
        return lhs > rhs if self.desc else lhs < rhs
    
    def _sift_up(self,index):
        """
        向上调整
        如果父节点和当前节点满足交换的关系
        (对于小顶堆是父节点元素更大,对于大顶堆是父节点更小),
        则持续将当前节点向上调整
        """
        while index:
            parent = (index-1) // 2
            
            if self._smaller(self.heap[parent],self.heap[index]):
                break
                
            self._swap(parent,index)
            index = parent
    
    def _sift_down(self,index):
        """
        向下调整
        如果子节点和当前节点满足交换的关系
        (对于小顶堆是子节点元素更小,对于大顶堆是子节点更大),
        则持续将当前节点向下调整
        """
        # 若存在子节点
        while index*2+1 < self.size:
            smallest = index
            left = index*2+1
            right = index*2+2
            
            if self._smaller(self.heap[left],self.heap[smallest]):
                smallest = left
                
            if right < self.size and self._smaller(self.heap[right],self.heap[smallest]):
                smallest = right
                
            if smallest == index:
                break
            
            self._swap(index,smallest)
            index = smallest
    
    def _swap(self,i,j):
        self.heap[i],self.heap[j] = self.heap[j],self.heap[i]

LeetCode 703. 数据流中的第 K 大元素

题解:

class KthLargest:

    def __init__(self, k: int, nums: List[int]):
        self.heap = Heap()
        self.k = k
        for num in nums:
            self.heap.push(num)
            if self.heap.size > k:
                self.heap.pop()


    def add(self, val: int) -> int:
        self.heap.push(val)
        if self.heap.size > self.k:
            self.heap.pop()
        return self.heap.top()

作者:MiloMusiala
链接:https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/solution/python-dong-hua-shou-xie-shi-xian-dui-by-ypz2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值