heapq源码详解

83 阅读1分钟

1、调包实验

import heapq
heap = [2,3,1,4,9,0,5]
heapq.heapify(heap)
print(heap)

 

 2、源码实验

## 定义相关的函数
def heapify(x):
    """Transform list into a heap, in-place, in O(len(x)) time."""
    n = len(x)
    # Transform bottom-up.  The largest index there's any point to looking at
    # is the largest with a child index in-range, so must have 2*i + 1 < n,
    # or i < (n-1)/2.  If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
    # j-1 is the largest, which is n//2 - 1.  If n is odd = 2*j+1, this is
    # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
    for i in reversed(range(n//2)):
        siftup(x, i)

def siftup(heap, pos):
    endpos = len(heap)
    startpos = pos
    newitem = heap[pos]
    # Bubble up the smaller child until hitting a leaf.
    childpos = 2*pos + 1    # leftmost child position
    while childpos < endpos:
        # Set childpos to index of smaller child.
        rightpos = childpos + 1
        if rightpos < endpos and not heap[childpos] < heap[rightpos]:
            childpos = rightpos
        # Move the smaller child up.
        heap[pos] = heap[childpos]
        pos = childpos
        print("current smaller node index is:",pos,"current smaller node value is",heap[pos])
        childpos = 2*pos + 1
    # The leaf at pos is empty now.  Put newitem there, and bubble it up
    # to its final resting place (by sifting its parents down).
    heap[pos] = newitem
    print("siftup result:",heap)
    siftdown(heap, startpos, pos)


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 newitem < parent:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem
    print("sift down result:",heap)

2.1 首先通过n//2不断找到最后一个叶子节点的父节点,从该节点开始调整堆,并进行下沉和上浮

## 很明显n=7,所以可得最后一个节点的父节点为index=2,即1
print(len(heap)//2)
print(range(len(heap)//2))
print(reversed(range(len(heap)//2)))
print([x for x in reversed(range(len(heap)//2))])

2.2 然后执行子节点的上浮,也就是上面那个父节点的子节点中最小的节点上浮过去 

### 1、第一次调整,首先输入heap=[2,3,1,4,9,0,5],执行_shiftup代码
heap = [2,3,1,4,9,0,5]
siftup(heap,2)

### 2、第二次调整,输入heap
siftup(heap,1)

 

### 3、第三次调整,输入heap
siftup(heap,0)