【数据结构排序算法篇】----堆排序【实战演练】

本文介绍了堆排序算法的工作原理,包括最大堆和最小堆的构建,堆排序的过程,以及堆排序在实际中的优势,如时间复杂度稳定、空间效率和适用场景。同时提供了Java实现和面试题示例,包括自定义数据类型的堆排序方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

作为一名对技术充满热情的学习者,我一直以来都深刻地体会到知识的广度和深度。在这个不断演变的数字时代,我远非专家,而是一位不断追求进步的旅行者。通过这篇博客,我想分享我在某个领域的学习经验,与大家共同探讨、共同成长。请大家以开放的心态阅读,相信你们也会在这段知识之旅中找到启示。


前言

继续继续继续,今天我们还是排序算法,认识新的排序算法----堆排序


一、什么是堆排序

堆排序是一种基于比较的排序算法,它利用二叉堆这种数据结构的特性来对元素进行排序。二叉堆是一个近似完全二叉树的数据结构,它分为两种类型:

  1. 最大堆:任何一个父节点的值都大于或等于它的孩子节点的值。
  2. 最小堆:任何一个父节点的值都小于或等于它的孩子节点的值。

在堆排序算法中,最大堆用于升序排序,而最小堆则用于降序排序。下面是堆排序算法的基本步骤:

  1. 建立堆:将待排序的数组构造成一个最大堆(升序排序)。这个步骤是将数组转换成最大堆的过程,通常可以从最后一个非叶子节点开始向上进行调整。

  2. 堆排序

    • 从堆中逐个取出元素进行排序;
    • 每一次将根节点(即当前最大值)与堆中最后一个元素交换,并对剩余的堆结构进行调整,重建最大堆;
    • 这个过程一直重复,直到堆中仅剩下一个元素,排序完成。

堆排序过程的伪代码如下:

function heapSort(arr):
    n = length(arr)
    
    # 构建最大堆
    for i from n/2 - 1 down to 0:
        heapify(arr, n, i)
    
    # 一个一个地从堆顶取出元素
    for i from n - 1 down to 0:
        # 将当前根节点,也就是最大值移动到数组末尾
        swap arr[0] with arr[i]
        
        # 在减小堆的大小后,恢复堆的性质
        heapify(arr, i, 0)

# 将一个数组转换成最大堆
function heapify(arr, n, i):
    largest = i    # 初始化最大为根节点
    l = 2 * i + 1  # 左子节点
    r = 2 * i + 2  # 右子节点
    
    # 如果左子节点大于根节点
    if l < n and arr[l] > arr[largest]:
        largest = l
    
    # 如果右子节点大于最大目前节点
    if r < n and arr[r] > arr[largest]:
        largest = r
    
    # 如果最大值不是根节点,则进行交换
    if largest != i:
        swap arr[i] with arr[largest]
        
        # 递归地定义子堆为最大堆
        heapify(arr, n, largest)

堆排序的时间复杂度是O(nlogn),其中n是数组的长度。这是因为创建最大堆的过程是O(n),而从最大堆中取出每个元素进行排序的过程是O(logn)的(因为需要进行堆调整),这样的操作需要进行n次。堆排序是一个不稳定的排序算法,但是它的优势在于不需要额外的存储空间(原地排序)。

二、练习

用堆排序堆下面数组进行排序(最大堆)
int[] arr = {3, 5, 1, 6, 4, 7, 2};

堆排序的详细步骤如下:

第一步:构建最大堆
我们需要将数组转换成最大堆。我们从最后一个非叶子节点开始(即数组中间位置的节点),到根节点位置进行调整。对于给定数组,最后一个非叶子节点的索引是 (arr.length - 1) / 2

  1. (7 - 1) / 2 = 3 -> 第3个位置的元素 6 开始调整,确保它的子树遵循最大堆的性质。因为它的孩子 47 已经满足最大堆的性质(7 > 6 > 4),所以不必调整。

  2. 接下来是位置2的元素 1,现在我们需要调整以确保子树满足最大堆性质。1 需要和它的孩子 64 中较大的一个交换,即 6。交换后的数组如下:

    int[] arr = {3, 5, 6, 1, 4, 7, 2};

  3. 现在是位置1的元素 5。它的孩子节点是 14,都已满足最大堆的性质,不必调整。

  4. 最后,我们调整根节点位置0的元素 3。它与两个子节点 5</

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值