📜  排序算法可视化:堆排序(1)

📅  最后修改于: 2023-12-03 15:25:55.934000             🧑  作者: Mango

排序算法可视化:堆排序

堆排序是一种高效的排序算法,其核心是建立一个最大/最小堆,然后将堆顶元素与堆底元素交换,不断缩小堆的范围,直到整个序列有序。

堆是一种特殊的二叉树,它同时满足以下两个条件:

  • 结构性:堆是一颗完全二叉树,也就是说除了最后一层,其他层都是满的,最后一层从左往右填满,如果最后一层没有填满,则只能缺失右边的若干节点。
  • 堆序性:堆中每一个节点都必须满足某种特定的顺序关系,例如最大堆中,父节点的值大于等于它的左右子节点的值。

堆可以分为最大堆和最小堆,分别以最大值和最小值为堆顶。在堆排序中,我们需要用到的是最大堆,因为堆排序是将最大值不断放到末尾。

算法步骤
  1. 将原始序列构建成最大堆,此处需要从最后一个非叶子节点开始进行调整。
  2. 将堆顶元素与堆底元素交换。
  3. 重新构建最大堆,此时堆的范围缩小一个元素。
  4. 重复上述步骤,直到整个序列有序。
可视化实现

下面是使用Python实现的可视化堆排序算法。其中,使用了pygame库进行可视化,每一次构建最大堆或交换堆顶元素都会更新界面。

import pygame
import random

def heapify(nums, n, i, screen, width, height):
    largest = i
    l = 2 * i + 1
    r = 2 * i + 2

    if l < n and nums[largest] < nums[l]:
        largest = l

    if r < n and nums[largest] < nums[r]:
        largest = r

    if largest != i:
        nums[i], nums[largest] = nums[largest], nums[i]
        draw(nums, screen, width, height)
        heapify(nums, n, largest, screen, width, height)


def heap_sort(nums, screen, width, height):
    n = len(nums)

    for i in range(n//2 - 1, -1, -1):
        heapify(nums, n, i, screen, width, height)

    for i in range(n-1, 0, -1):
        nums[0], nums[i] = nums[i], nums[0]
        draw(nums, screen, width, height)
        heapify(nums, i, 0, screen, width, height)


def draw(nums, screen, width, height):
    screen.fill((255, 255, 255))
    margin = 5
    size = 10
    for i, num in enumerate(nums):
        x = i * size + margin
        y = height - num * size
        pygame.draw.rect(screen, (0, 0, 0), (x, y, size, num * size))
    pygame.display.flip()


def main():
    nums = [random.randint(1, 100) for _ in range(50)]
    pygame.init()
    size = width, height = 520, 400
    screen = pygame.display.set_mode(size)
    pygame.display.set_caption("Heap Sort")
    draw(nums, screen, width, height)
    heap_sort(nums, screen, width, height)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return

if __name__ == '__main__':
    main()

分析

时间复杂度:O(nlogn)

空间复杂度:O(1)

堆排序是一种不稳定的排序算法,实际应用中较少使用,但其对于最坏情况的表现比快排要好。在可视化实现中,可以看到每一次堆重构和交换都能够在界面上得到体现,方便我们理解算法的核心思想。