LeetCode—2. Heap Sorting Algorithm

One and two forks

  Binary heap is essentially a complete binary tree, which is divided into two types:

  1. Maximum heap: The value of any parent node of the maximum heap is greater than or equal to the value of its left and right child nodes.
    Insert picture description here
  2. Minimum heap: The value of any parent node of the smallest heap is less than or equal to the value of its left and right child nodes.
      The root node of a binary heap is called the top of the heap. The characteristics of the largest heap and the smallest heap determine that the top of the largest heap is the largest element in the entire heap; the top of the smallest heap is the smallest element of the entire heap.

Second, the self-adjustment of the heap

1. Insert node

  Let's take the smallest heap as an example to see how the binary heap is adjusted?
Insert picture description here

As shown in the figure, inserting node 0 into the binary heap, node 0 and node 5 do not meet the structure of the binary heap, so node 0 and node 5 are exchanged; node 0 and node 3 do not meet the structure of the binary heap, so Node 0 and node 3 are exchanged, and at the same time, after the exchange, see if node 3 and node 5 meet the structure of the binary tree, yes! Node 0 and node 1 do not meet the structure of the binary tree, they are exchanged, and at the same time, see whether node 1 and node 3 meet the structure of the binary tree in the same way.

Main principles:

Whether the inserted node and the parent node meet the structure of the binary heap, if not, the inserted node is adjusted upward, and the parent node is adjusted downward.

2. Delete the node

  Deleting a node means popping a node from the heap, generally popping the top of the heap. Let's take the smallest heap as an example to show how the binary heap deletes nodes?
Insert picture description here
  When we delete the top of the smallest heap (not completely delete, but replace to the end)

As shown in the figure, first swap the top node 1 with the last leaf node 10. Then see if the node 10 meets the structure of the binary heap, if not, adjust downwards, and the node 10 exchanges with the small leaf node 2 (if it exchanges with the leaf node 3, the binary heap structure is still not satisfied), Node 10 still does not meet the minimum heap definition, and exchanges with leaf node 7.

3. Build a binary heap

  Build a binary heap. It is to adjust an unordered complete binary tree to a binary heap, which is essentially to make all non-leaf nodes sink at once.

  • bottom up
  • Top down

Insert picture description here
The following describes the bottom-up approach to adjust the above unordered binary tree to the smallest heap:

First, node 6 exchanges with node 10, node 2 exchanges with node 3. Since node 5 and node 2 are leaf nodes in the original binary tree, there is no need to adjust downwards. Node 1 is exchanged with node 7, node 7 is adjusted downward, node 7 is exchanged with node 5, and the minimum binary heap is established!

Three, the realization of the heap

  Although the binary heap is a complete binary tree, its storage method is not chain storage, but sequential storage . In other words, all the nodes of the binary heap are stored in the array .
  So, how to locate the parent node of the child node or the child node of the parent node?
Insert picture description here
  The binary heap can be converted into an array. Arrays can also be converted into binary heaps. The index relationship between the child node and the parent node in the array is as follows:

If the index of the parent node is n, the indexes of the two child nodes are 2n+1, 2n+2 respectively.
As shown in the figure above, the indexes of nodes 6, 9, and 10 are 3,
7, and
8. 7 = 2×3 + 1 8 = 2×3 + 2
If the index of the child node is known, (child node index-1)/ 2 and then round down.

Four, LeetCode

  215. Find the k-th largest element in the unsorted array (you need to find the k-th largest element after the array is sorted)

Input: [3,2,1,5,6,4] and k
output: 5

class Solution():
    def findKthLarget(self, nums, k):
        self._k = k
        return self.heap_sort(nums)

    def heap_sort(self, nums):
        """
        堆排序
        将根节点取出与最后一位做对调,对前面len-1个节点继续进行堆调整过程
        :param nums: 数组
        :return:
        """
        self.build_max_heap(nums)
        print(nums)
        cnt = 0
        # 调整后列表的第一个元素就是这个列表中最大的元素,
        # 将其与最后一个元素交换,然后将剩余的列表再递归的调整为最大堆
        for i in range(len(nums) - 1, -1, -1):
            nums[0], nums[i] = nums[i], nums[0]
            cnt += 1
            if cnt == self._k:
                return nums[i]
            self.max_heapify(nums, i, 0)

    def build_max_heap(self, nums):
        """
        构建最大堆
        :param nums: 数组
        :return: 最大堆
        """
        length = len(nums)
        for i in range((length - 2) // 2, -1, -1):  # 自底向上建堆
            self.max_heapify(nums, length, i)

    def max_heapify(self, nums, length, root):
        '''
        调整列表中的元素并保证以root为根的堆是一个大根堆
        给定某个节点的下标root,这个节点的父节点、左子节点、右子节点的下标都可以被计算出来。
        索引从0开始时
        父节点:(root-1)//2
        左子节点:2*root + 1
        右子节点:2*root + 2  即:左子节点 + 1
        '''
        left = 2 * root + 1
        right = left + 1
        larger = root
        if left < length and nums[larger] < nums[left]:
            larger = left
        if right < length and nums[larger] < nums[right]:
            larger = right
        # larger的值等于左节点或者右节点的值时,需要做堆调整
        if larger != root:
            nums[larger], nums[root] = nums[root], nums[larger]
            # 递归的对子树做调整
            self.max_heapify(nums, length, larger)


def main():
    nums = [3,2,1,5,6,4]
    k = 2
    s = Solution()
    kth_element = s.findKthLarget(nums, k)
    print('数组中第%d个最大元素为%d' % (k, kth_element))


if __name__ == '__main__':
    main()
[6, 5, 4, 3, 2, 1]
数组中第2个最大元素为5

Guess you like

Origin blog.csdn.net/weixin_46649052/article/details/114379527