繁体   English   中英

有人可以在这段代码中解释 _siftup 和 _siftdown 吗?

[英]Can someone explain _siftup and _siftdown in this piece of code?

    def remove(self, heap, element):
        ind = heap.index(element)
        heap[ind] = heap[-1]
        del heap[-1]

        if ind < len(heap):
            heapq._siftup(heap, ind)
            heapq._siftdown(heap, 0, ind)

我正在发送一个堆和一个需要删除的元素。 因此 ind 获取堆内该元素的indheap[ind] = heap[-1]将该元素放在顶部del heap[-1]删除该元素。 但是下面的代码在做什么? 为什么 ind 会小于堆的长度? 我不知道这里发生了什么。

heap[ind] = heap[-1]将该元素放在顶部

不,它实际上在复制该指数的最后一个元素ind其中element被发现,使element实际上是删除(通过覆盖)。

为什么ind会小于堆的长度?

假设该element实际出现在堆中,则ind可以是 0 和len(heap)之间的任何值。 因为通过执行delete heap[-1]减小了堆的大小,考虑到删除的长度, ind甚至可能等于len(heap)

所以我们可以有两种可能; 任何一个:

  • ind == len(heap) :当在堆的最后发现element时会发生这种情况:边界情况。 通过delete heap[-1]减少了堆的长度,因此我们有这种相等性。 在这种情况下没有什么可做的,因为delete heap[-1]删除了必须删除的元素。

  • ind < len(heap) :这是更通用的情况。 在这种情况下,我们没有删除element ,但其它元素。 该元素被复制到索引ind ,因此我们实际上删除了element ......通过覆盖它。 剩下要做的唯一一件事是恢复堆属性,这确保一个值不小于其父级且不大于其任一子级。

    这就是我们需要调用 sift 函数的原因。 移动到索引ind的值可能碰巧违反了堆属性。

但是下面的代码在做什么?

一些例子可能会阐明正在发生的事情

示例 1

假设我们有这个(最小)堆:[1, 2, 3] 这是这棵树:

             1
            / \
           2   3

...我们调用这个函数来删除 1,然后是这样的:

  1. 我们确定 1 出现在索引 0 ( ind )

  2. 值 3 被复制到索引 0,因此堆临时有一个重复条目:[3, 2, 3]

  3. 最后一个条目被删除,所以我们得到[3, 2],也就是这棵树:

     3 / 2
  4. 由于这棵树违反了堆属性,我们调用heapq._siftdown 该方法会将值 3向下移动,直到它位于恢复堆属性的位置。 这将导致堆 [2, 3]:

     2 / 3

示例 2

假设我们有这个(最小)堆:[1, 5, 2, 6, 7, 3] 这是这棵树:

              _1_
            /     \
           5       2
          / \     /
         6   7   3

...我们调用这个函数来删除 6,然后会发生这样的事情:

  1. 我们确定 6 出现在索引 3 ( ind )

  2. 值 3 被复制到索引 3,因此堆临时有一个重复条目:[1, 5, 2, 3, 7, 3]

  3. 最后一个条目被删除,所以我们得到 [1, 5, 2, 3, 7],也就是这棵树:

     _1_ / \\ 5 2 / \\ 3 7
  4. 由于这棵树违反了堆属性,我们调用heapq._siftup 该方法会将值 3向上移动直到它位于恢复堆属性的位置。 这将导致堆 [1, 3, 2, 5, 7]:

     _1_ / \\ 3 2 / \\ 5 7

因此,在示例 1 中,我们看到需要进行筛选的情况,而在示例 2 中需要进行筛选。 这就是调用两个sift 方法的原因:这样可以确保移动的值将被带到它遵守堆属性的位置。 请注意,两个方法调用中的最多一个实际上会移动元素,而另一个调用是无害的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM