Python 中 Heapify 函数的意外结果

Unexpected Result from Heapify Function in Python

我运行下面这段代码

from heapq import heappop,heappush,heapify
nums = [12,3,-2,6,4,8,9]
heapify(nums)
print(nums)

并得到如下结果: [-2, 3, 8, 6, 4, 12, 9] 但我希望得到以下结果: [-2,4,3,12,6,8,9] 因为我希望我们在维护堆数据结构的同时将每个项目从 nums(从 12 开始,一个一个地)推入一个空列表。谁能给我一些指导,为什么我错了?

让我们画出您的初始数组:[12,3,-2,6,4,8,9]

               12
            /      \
           3       -2
         /   \    /   \
        6     4  8     9

heapify函数不会重复插入建堆。它使用 Floyd 算法在 O(n) 时间内将数组重新排列为堆顺序。在 https://github.com/python/cpython/blob/master/Lib/heapq.py 中搜索 "heapify"。相关代码为:

for i in reversed(range(n//2)):
    _siftup(x, i)

(出于某种未知原因,heapq 的作者决定将节点向叶级移动的操作称为“_siftup”,这非常令人困惑。大多数人将此操作称为“_siftdown”。如果您检查代码,虽然,节点肯定正在向叶级别移动。)

无论如何,堆中有7个节点。这将影响的第一个节点位于数组中的索引 3 处:值为 6 的节点。该节点无需执行任何操作,因为该节点已经处于叶级别。然后它尝试移动索引 2(值 -2)处的节点,但它根本没有筛选。值为 3 的节点也不会筛选。所以我们剩下根节点 12.

12 比两个 children 都大,所以它与最小的交换,给出:

               -2
            /      \
           3       12
         /   \    /   \
        6     4  8     9

而且它比这两个 children 都大,所以它再次与最小的交换:

               -2
            /      \
           3        8
         /   \    /   \
        6     4  12    9

那么数组表示就是[-2, 3, 8, 6, 4, 12, 9].

我觉得叫_siftup是因为(在CS课上),父节点也叫根节点,所以函数写起来的时候,树倒过来了