python heapq源代码_siftdown

时间:2014-07-28 23:41:25

标签: python

PYTHON:

def _siftdown(heap, startpos, pos):
    newitem = heap[pos]
    # Follow the path to the root, moving parents down until finding a place
    # newitem fits.
    while pos> startpos:
        parentpos = (pos - 1)>> 1
        parent = heap[parentpos]
        if cmp_lt(newitem, parent):
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem

我只是查看了heapq源代码,有人能解释第6行的内容吗?什么是>>运算符及其工作原理?

2 个答案:

答案 0 :(得分:2)

>>运算符表示bitwise right shift。向右移位(非负整数)相当于除以2并向下舍入。换句话说,spam >> 1spam // 2是相同的。

那么,为什么要使用>>?一些CPU - 尤其是较旧的CPU - 可以比分区更快地执行比特移位。大多数现代C编译器会在适当的时候将n / 2优化为n >> 1,但是较旧的编译器不会。当然,这在Python中几乎没有区别,但是大多数传统的堆实现 - 您将在数据结构教科书中看到的类型 - 将使用>>。最重要的是,对于某些人(从这些教科书中学习的那种人),算法中的>>是一个很好的信号,它是对数的。


  

所以这个parentpos = (pos-1) >> 1行试图返回其父级的索引。但为什么减去1?假设当前索引是4,这是树的第三级,然后你减去1得到3.并且二进制数是11,如果你向右移动那么它将是索引1,而不是父索引。

阅读the documentation的顶部:

  

此实现使用的数组heap[k] <= heap[2*k+1]heap[k] <= heap[2*k+2]适用于所有k ...

因此,对于k=1,孩子是2*1+1 = 32*1+2 = 4。如下一段所述,这可能令人困惑:

  

以下API在两个方面与教科书堆算法不同:(a)我们使用从零开始的索引。这使得节点的索引与其子节点的索引之间的关系略显不明显,但更适合,因为Python使用从零开始的索引。

所以,您希望1的孩子是23,但如果您以0为基础的术语来考虑它,那么您应该期待0的孩子{1}}为121的子女为34

答案 1 :(得分:1)

>>是右移运营商。它会丢弃最右边的位,这与除以2并忽略其余部分相同。所以该行可以写成parentpos = (pos - 1) // 2

Python的堆是从零开始的,因此节点 i 2 * i + 12 * i + 2都有子项。它的父母位于(i - 1) // 2

siftdown 的作用是向上移动一个值(通过与父项交换),直到父级小于子级。