Home  >  Article  >  Backend Development  >  How to implement python's built-in heap

How to implement python's built-in heap

WBOY
WBOYforward
2023-04-28 20:40:131323browse

    1. Introduction

    The heap, also known as the priority queue, is a complete binary tree. The value of each of its parent nodes will only be less than or equal to All child nodes (values ​​of). It uses an array to implement: counting from zero, for all k, there are heap[k] . For the sake of comparison, non-existent elements are considered to be infinite. The most interesting feature of the heap is that the smallest element is always at the root node: heap[0].

    Python's heap is generally a minimum heap, which is different from the content in many textbooks. Most of the textbooks use the maximum heap. Due to the way the heap is expressed, it is stored from top to bottom and from left to right, which is different from the content in many textbooks. Lists are very similar, so to create a heap, you can use a list initialized to [], or you can convert a list into a heap through a function heapify(). The following are related operations on the heap in python. It can be seen from this that python indeed treats the heap as a list.

    How to implement pythons built-in heap

    2. Heap related operations

    heapq.heappush(heap, item)

    Add the item value to the heap and keep it Heap immutability. It will automatically exchange related elements according to the minimum heap feature in Python so that the root node element of the heap is never larger than the child node elements.

    The original data is a heap

    import heapq
    
    h = [1, 2, 3, 5, 7]
    heapq.heappush(h, 2)
    print(h)
    #输出
    [1, 2, 2, 5, 7, 3]

    The operation process is as follows:

    1. The following is the initial state

    How to implement pythons built-in heap

    2. After adding 2 elements

    How to implement pythons built-in heap

    3. Since it does not meet the characteristics of the minimum heap, it is exchanged with 3

    How to implement pythons built-in heap

    4. In line with the characteristics of the minimum heap, the exchange ends, so the result is [1, 2, 3, 5, 7, 3]

    Original There is data that is not in the heap

    import heapq
    
    h = [5, 2, 1, 4, 7]
    heapq.heappush(h, 2)
    print(h)
    #输出
    [5, 2, 1, 4, 7, 2]

    It can be seen that when the push operation is performed and the element is not in the heap, the element is added by default according to the append method of the list

    heapq.heappop( heap)

    Pop and return the smallest element of the heap, keeping the heap unchanged. If the heap is empty, throw IndexError. Using heap[0] , it is possible to access only the smallest element without popping it.

    The original data is a heap

    import heapq
    
    h = [1, 2, 3, 5, 7]
    heapq.heappop(h)
    print(h)
    #输出
    [2, 5, 3, 7]

    The operation process is as follows:

    1.Initial state

    How to implement pythons built-in heap

    2. The top element of the heap is deleted, and the last element is moved to the top of the heap

    How to implement pythons built-in heap

    3. The elements are exchanged according to the characteristics of python's minimum heap, because 7>2, exchange 7 and 2

    How to implement pythons built-in heap

    ##4. Exchange elements according to the characteristics of Python's minimum heap. Since 7>5, exchange 7 and 5

    How to implement pythons built-in heap

    5. Meets the requirements of the heap, that is, the result is [2, 5, 3, 7]

    The original data is not a heap

    import heapq
    
    h = [5, 2, 1, 4, 7]
    heapq.heappop(h)
    print(h)
    
    [1, 2, 7, 4]

    The operation process is as follows:

    1. The initial state obviously does not conform to the nature of the heap

    How to implement pythons built-in heap

    2. Remove the most For the above element (the first element), rearrange the remaining elements into the heap

    How to implement pythons built-in heap

    3. According to the characteristics of python’s minimum heap, 2>1 exchanges 2 and 1

    How to implement pythons built-in heap

    4. Meets the requirements of the heap, the result is [1, 2, 7, 4]

    heapq.heappushpop(heap, item)

    Put the item into the heap, then pop it out and return the smallest element of the heap. This combined operation runs more efficiently than calling heappush() first and then heappop(). It should be noted that the popped element must be at the top or end of the heap. That is to say, when an element is inserted and the smallest element is compared, the top element of the heap is always compared. If the inserted element is greater than or equal to the top element of the heap, The heap will not change. When the inserted element is smaller than the top element of the heap, the heap will be processed according to the minimum heap characteristics of the Python heap.

    The original data is a heap

    import heapq
    
    h = [1, 2, 3, 5, 7]
    min_data = heapq.heappushpop(h, 2)
    print(min_data)
    print(h)
    #输出
    1
    [2, 2, 3, 5, 7]

    The operation process is as follows

    1. Initial state

    How to implement pythons built-in heap ##2.Insert element 2

    3.删除最小元素,刚好是堆顶元素1,并使用末尾元素2代替

    How to implement pythons built-in heap

    4.符合要求,即结果为[2, 2, 3, 5, 7]

    原有数据不是堆

    h = [5, 2, 1, 4, 7]
    min_data = heapq.heappushpop(h, 2)
    print(min_data)
    print(h)
    min_data = heapq.heappushpop(h, 6)
    print(min_data)
    print(h)
    
    #输出
    2
    [5, 2, 1, 4, 7]
    5
    [1, 2, 6, 4, 7]

    对于插入元素6的操作过程如下

    1.初始状态

    How to implement pythons built-in heap

    2.插入元素6之后

    How to implement pythons built-in heap

    3.发现元素6大于堆顶元素5,弹出堆顶元素5,由堆尾元素6替换

    How to implement pythons built-in heap

    4.依据python的最小堆特性,元素6>元素1且元素6>元素2,但元素2>元素1, 交换6与1

    How to implement pythons built-in heap

    5.符合要求,则结果为[1, 2, 6, 4, 7]

    由结果可以看出,当插入元素小于堆顶元素时,则堆不会发生改变,当插入元素大于堆顶元素时,则堆依据python堆的最小堆特性处理。

    heapq.heapify(x)

    将列表转换为堆。

    h = [1, 2, 3, 5, 7]
    heapq.heapify(h)
    print(h)
    h = [5, 2, 1, 4, 7]
    heapq.heapify(h)
    print(h)
    #输出
    [1, 2, 3, 5, 7]
    [1, 2, 5, 4, 7]

    会自动将列表依据python最小堆特性进行重新排列。

    heapq.heapreplace(heap, item)

    弹出并返回最小的元素,并且添加一个新元素item,这个单步骤操作比heappop()加heappush() 更高效。适用于堆元素数量固定的情况。

    返回的值可能会比添加的 item 更大。 如果不希望如此,可考虑改用heappushpop()。 它的 push/pop 组合会返回两个值中较小的一个,将较大的值留在堆中。

    import heapq
    
    h = [1, 2, 3, 5, 7]
    heapq.heapreplace(h, 6)
    print(h)
    h = [5, 2, 1, 4, 7]
    heapq.heapreplace(h, 6)
    print(h)
    #输出
    [2, 5, 3, 6, 7]
    [1, 2, 6, 4, 7]

    原有数据是堆

    对于插入元素6的操作过程如下:

    1.初始状态

    How to implement pythons built-in heap

    2.弹出最小元素,只能弹出堆顶或者堆尾的元素,很明显,最小元素是1,弹出1,插入元素是6,代替堆顶元素

    How to implement pythons built-in heap

    3.依据python堆的最小堆特性,6>2,交换6与2

    How to implement pythons built-in heap

    4.依据python堆的最小堆特性,6>5,交换6与5

    How to implement pythons built-in heap

    5.符合要求,则结果为[2, 5, 3, 6 ,7]

    原有数据不是堆

    对于插入元素6的操作过程如下:

    1.初始状态

    How to implement pythons built-in heap

    2.对于数据不为堆的情况下,默认移除第一个元素,这里就是元素5,然后插入元素6到堆顶

    How to implement pythons built-in heap

    3.依据python的最小堆特性,元素6>1,交换元素6与1

    How to implement pythons built-in heap

    4.符合要求,即结果为[1, 2, 6, 4, 7

    heapq.merge(*iterables, key=None, reverse=False)

    将多个已排序的输入合并为一个已排序的输出(例如,合并来自多个日志文件的带时间戳的条目)。 返回已排序值的 iterator。注意需要是已排序完成的可迭代对象(默认为从小到大排序),当reverse为True时,则为从大到小排序。

    heapq.nlargest(n, iterable, key=None)

    从 iterable 所定义的数据集中返回前 n 个最大元素组成的列表。 如果提供了 key 则其应指定一个单参数的函数,用于从 iterable 的每个元素中提取比较键 (例如 key=str.lower)。

    等价于: sorted(iterable, key=key, reverse=True)[:n]。

    import time
    import heapq
    
    h = [1, 2, 3, 5, 7]
    
    size = 1000000
    start = time.time()
    print(heapq.nlargest(3, h))
    for i in range(size):
        heapq.nlargest(3, h)
    print(time.time() - start)
    
    start = time.time()
    print(sorted(h, reverse=True)[:3:])
    for i in range(size):
        sorted(h, reverse=True)[:3:]
    print(time.time() - start)
    #输出
    [7, 5, 3]
    1.6576552391052246
    [7, 5, 3]
    0.2772986888885498
    [7, 5, 4]

    由上述结构可见,heapq.nlargest与sorted(iterable, key=key, reverse=False)[:n]功能是类似的,但是性能方面还是sorted较为快速。

    heapq.nsmallest(n, iterable, key=None)

    从 iterable 所定义的数据集中返回前 n 个最小元素组成的列表。 如果提供了 key 则其应指定一个单参数的函数,用于从 iterable 的每个元素中提取比较键 (例如 key=str.lower)。 等价于: sorted(iterable, key=key)[:n]。

    import time
    import heapq
    
    h = [1, 2, 3, 5, 7]
    
    size = 1000000
    start = time.time()
    print(heapq.nsmallest(3, h))
    for i in range(size):
        heapq.nsmallest(2, h)
    print(time.time() - start)
    
    start = time.time()
    print(sorted(h, reverse=False)[:3:])
    for i in range(size):
        sorted(h, reverse=False)[:2:]
    print(time.time() - start)
    #输出
    [1, 2, 3]
    1.1738648414611816
    [1, 2, 3]
    0.2871997356414795

    由上述结果可见,sorted的性能比后面两个函数都要好,但如果只是返回最大的或者最小的一个元素,则使用max和min最好。

    3.堆排序

    由于在python中堆的特性是最小堆,堆顶的元素始终是最小的,可以将序列转换成堆之后,再使用pop弹出堆顶元素来实现从小到大排序。具体实现如下:

    from heapq import heappush, heappop, heapify
    
    
    def heapsort(iterable):
        h = []
        for value in iterable:
            heappush(h, value)
        return [heappop(h) for i in range(len(h))]
    
    
    def heapsort2(iterable):
        heapify(iterable)
        return [heappop(iterable) for i in range(len(iterable))]
    
    
    data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
    
    print(heapsort(data))
    print(heapsort2(data))
    #输出
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    4.堆中元素可以是元组形式,主要用于任务优先级

    from heapq import heappush, heappop
    
    h = []
    heappush(h, (5, 'write code'))
    heappush(h, (7, 'release product'))
    heappush(h, (1, 'write spec'))
    heappush(h, (3, 'create tests'))
    print(h)
    print(heappop(h))
    
    [(1, 'write spec'), (3, 'create tests'), (5, 'write code'), (7, 'release product')]
    (1, 'write spec')

    上述操作流程如下:

    1.当进行第一次push(5, ‘write code’)时

    How to implement pythons built-in heap

    2.当进行第二次push(7, ‘release product’)时,符合堆的要求

    How to implement pythons built-in heap

    3.当进行第三次push(1, ‘write spec’)时,

    How to implement pythons built-in heap

    4.依据python的堆的最小堆特性,5>1 ,交换5和1

    How to implement pythons built-in heap

    5.当进行最后依次push(3, ‘create tests’)时

    How to implement pythons built-in heap

    6.依据python堆的最小堆特性,7>3,交换7与3

    How to implement pythons built-in heap

    7.符合要求,因此结果为[(1, ‘write spec’), (3, ‘create tests’), (5, ‘write code’), (7, ‘release product’)],弹出元素则是堆顶元素,数字越小,优先级越大。

    The above is the detailed content of How to implement python's built-in heap. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete