Python implementation of binary heap and big root heap

Python

binary heap

A binary heap is a special kind of heap. A binary heap is a complete binary tree or an approximate complete binary tree. The binary heap satisfies the heap characteristics: the key value of the parent node always maintains a fixed order relative to the key value of any child node, and the left and right subtrees of each node are a binary heap.
The max heap is when the key value of the parent node is always greater than or equal to the key value of any child node. The min heap is when the key value of the parent node is always less than or equal to the key value of any child node.

Binary heap storage

Binary heaps are generally represented by arrays. If the root node's position in the array is 1, the child nodes at the nth position are at 2n and 2n+1, respectively. So the children at position 1 are at 2 and 3, and the children at position 2 are at 4 and 5. And so on. This 1-based array storage makes it easy to find parent and child nodes.
If the subscript of the storage array is based on 0, then the child nodes of the node with subscript i are 2i + 1 and 2i + 2; the subscript of its parent node is ⌊floor((i − 1) ∕ 2)⌋, the function floor (x), its function is "round down", or "round down", that is, take the largest integer not greater than x (different from "round down", round down is to directly take the closest requirement on the number axis The left value of the value, that is, the largest value not greater than the required value). For example, floor(1.1) and floor(1.9) both return 1.
Two heaps as shown below:

Save these two heaps in an array starting with 1:
Position: 1 2 3 4 5 6 7 8 9 10 11
Left image: 1 2 3 4 5 6 7 8 9 10 11
Right image : 11 9 10 5 6 7 8 1 2 3 4
For a very large heap, this storage is inefficient. Because the child node of the node is likely to be in another memory page. B-heap is a more efficient storage method, placing each subtree on the same memory page.
If you store the heap with a linked list of pointers, you need a way to access the leaf nodes. The nodes can be traversed sequentially by "threading" the binary tree.

Basic operation

insert node

Insert a new node at the very end of the array. Then adjust the child node and parent node from bottom to top (called up-heap or bubble-up, percolate-up, sift-up, trickle up, heapify-up, cascade-up operation): compare the current node with the parent node, Exchange if the heap property is not satisfied. So that the current subtree satisfies the properties of binary heap. The time complexity is O(log n).

delete node

Remove the root node for heap sort.
For max heaps, deleting the root node is deleting the max value; for min heaps, deleting the min value. Then, move the last node of the heap storage to fill the root node. Then adjust the parent node and its children from top to bottom: for max heap, if the parent node is smaller than the child node with the maximum value, the two are swapped. This operation is called down-heap or bubble-down, percolate-down, sift-down, trickle down, heapify-down, cascade-down, extract-min/max, etc. Until the current node and its children satisfy the heap property.

Construct a binary heap

An intuitive approach is to start with a single-node binary heap and insert one node at a time. Its time complexity is {\displaystyle O(n\log n)} O(n\log n).
The optimal algorithm is to start from a binary tree where node elements are placed arbitrarily, and perform the Max-Heapify algorithm when deleting the root node for each subtree from the bottom up (this is for the maximum heap) to make the current subtree a binary heap. . Specifically, assuming that all subtrees with height h have completed binary heapization, then for subtrees with height h+1, adjusting the root node along the branch of the largest child node takes at most h steps to complete Binary heaping. It can be shown that the time complexity of this algorithm is O(n).

code

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""


@author: gsharp
"""

class BinaryHeap:
    def __init__(self, n):
        self.heap = [0] * n
        self.size = 0

    def remove_min(self):
        removed = self.heap[0]
        self.size -= 1
        self.heap[0] = self.heap[self.size]
        self._down(0)
        return removed

    def add(self, value):
        self.heap[self.size] = value
        self._up(self.size)
        self.size += 1

    def _up(self, pos):
        while pos > 0:
            parent = (pos - 1) // 2
            if self.heap[pos] >= self.heap[parent]:
                break
            self.heap[pos], self.heap[parent] = self.heap[parent], self.heap[pos]
            pos = parent

    def _down(self, pos):
        while True:
            child = 2 * pos + 1
            if child >= self.size:
                break
            if child + 1 < self.size and self.heap[child + 1] < self.heap[child]:
                child += 1
            if self.heap[pos] <= self.heap[child]:
                break
            self.heap[pos], self.heap[child] = self.heap[child], self.heap[pos]
            pos = child


def test():
    h = BinaryHeap(10)
    h.add(5)
    h.add(7)
    h.add(9)
    h.add(4)
    h.add(3)
    print(h.heap)
    h.add(1)
    print(h.heap)
    h.add(2)
    print(h.heap)
    print(h.remove_min())
    print(h.remove_min())
    print(h.remove_min())


test()

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325332399&siteId=291194637