通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

为什么python没有大顶堆

python没有大顶堆的原因:在实际使用中,大顶堆并不是那么常用。此外,Python的设计哲学也与内置大顶堆不太相关,Python的优势在于其简单、易学、易用、可读性好等特点,而内置大顶堆对于一个通用的高级编程语言来说,显得过于专用和冗余。

一、python没有大顶堆的原因

Python没有内置大顶堆,是因为在实际使用中,大顶堆并不是那么常用。相比之下,小顶堆和普通的堆操作更具有广泛的应用场景,例如在排序算法、图论算法、贪心算法、动态规划等各种算法中都可以看到堆的身影。

此外,Python的设计哲学也与内置大顶堆不太相关。Python的优势在于其简单、易学、易用、可读性好等特点,而内置大顶堆对于一个通用的高级编程语言来说,显得过于专用和冗余。因此,Python通过标准库模块heapq提供了一组堆操作函数,使用者可以方便地根据需要构建小顶堆或者大顶堆,同时也避免了引入过多的不必要的数据类型和接口。

二、构造大顶堆的方法

堆是一种特殊的完全二叉树,使用数组存储二叉树时,若某个非叶子节点存储在下标为i的位置,其左右孩子节点分别存储在下标为2i+1和2i+2的位置。堆可以分为大顶堆和小顶堆,对大顶堆来说,任意非叶子节点不小于其左右孩子节点,对于小顶堆来说,任意非叶子节点不大于其左右孩子节点。若使用数组存储大顶堆,则满足:arr[i] >= arr[2i+1] && arr[i] >=arr[2i+2](i为非叶子节点的在数组中的下标)

基本思想:

  1. 从最后一个非叶子节点开始,逐一比较非叶子节点和其左右孩子节点
  2. 根据比较结果交换节点
  3. 因为交换可能导致孩子节点不再满足大顶堆的性质,所以需要对孩子节点进行调整。

三、python实现大顶堆的方法

python中虽然没有内置大顶堆数据结构,但可以通过其他方法实现大顶堆。实现步骤如下:

1、创建MaxHeap类

初始化,存储最大元素数量、元素值计算函数、元素列表,当前元素数量。

class MaxHeap(object):
    def __init__(self, max_size, fn):
        self.max_size = max_size
        self.fn = fn
        self.items = [None] * max_size
        self.size = 0

2、获取大顶堆各个属性

def __str__(self):
    item_values = str([self.fn(self.items[i]) for i in range(self.size)])
    return "Size: %d\nMax size: %d\nItem_values: %s\n" % (self.size, self.max_size, item_values)

3、检查大顶堆是否已满

@property
def full(self):
    return self.size == self.max_size

4、添加元素

def add(self, item):
    if self.full:
        if self.fn(item) < self.value(0):
            self.items[0] = item
            self._shift_down(0)
    else:
        self.items[self.size] = item
        self.size += 1
        self._shift_up(self.size - 1)

5、推出顶部元素

def pop(self):
    assert self.size > 0, "Cannot pop item! The MaxHeap is empty!"
    ret = self.items[0]
    self.items[0] = self.items[self.size - 1]
    self.items[self.size - 1] = None
    self.size -= 1
    self._shift_down(0)
    return ret

6、元素上浮

def _shift_up(self, idx):
    assert idx < self.size, "The parameter idx must be less than heap's size!"
    parent = (idx - 1) // 2
    while parent >= 0 and self.value(parent) < self.value(idx):
        self.items[parent], self.items[idx] = self.items[idx], self.items[parent]
        idx = parent
        parent = (idx - 1) // 2

7、元素下沉

def _shift_down(self, idx):
    child = (idx + 1) * 2 - 1
    while child < self.size:
        if child + 1 < self.size and self.value(child + 1) > self.value(child):
            child += 1
        if self.value(idx) < self.value(child):
            self.items[idx], self.items[child] = self.items[child], self.items[idx]
            idx = child
            child = (idx + 1) * 2 - 1
        else:
            break

延伸阅读1:什么是堆数据结构

堆是一种完全二叉树,复习一下完全二叉树的定义,完全二叉树的形式是指除了最后一层之外,其他所有层的结点都是满的,而最后一层的所有结点都靠左边。教材上定义如下:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

相关文章