排序-堆排序(Heap Sort)

堆排序(Heap Sort)是一种基于比较的排序算法,它利用了完全二叉树的特性,将待排序的序列构造成一个大顶堆(每个父节点的值都大于或等于其子节点的值)或小顶堆(每个父节点的值都小于或等于其子节点的值),然后通过交换堆顶元素与最后一个元素并调整剩余元素为新的堆,以此达到排序的目的。堆排序的时间复杂度为O(n log n),并且它是不稳定的排序算法。

堆排序的基本步骤:

  1. 输入数组并建立大顶堆。完成后,最大元素位于堆顶。
  2. 将堆顶元素(第一个元素)与堆底元素(最后一个元素)交换。完成交换后,堆的长度减 1 ,已排序元素数量加 1 。
  3. 从堆顶元素开始,从顶到底执行堆化操作(sift down)。完成堆化后,堆的性质得到修复。
  4. 循环执行第 2. 步和第 3. 步。循环 𝑛−1 轮后,即可完成数组排序。

时间复杂度和空间复杂度:

  • 时间复杂度:堆排序的时间复杂度为O(n log n),其中n是数组长度。构建初始堆的时间复杂度为O(n),之后每次调整堆的时间复杂度为O(log n),需要进行n-1次调整。

  • 空间复杂度:堆排序是原地排序算法,除了用于交换的少量变量外,不需要额外的存储空间,因此其空间复杂度为O(1)。

不稳定性**:

堆排序是不稳定的排序算法,因为在调整堆的过程中,相等的元素可能会交换顺序。

堆排序的示例图如下:

堆排序的实现Java代码如下:

java 复制代码
public class HeapSort {
    // 调整大顶堆
    private static void heapify(int[] arr, int n, int i) {
        int largest = i; // 初始化最大值为根
        int left = 2 * i + 1; // 左子节点
        int right = 2 * i + 2; // 右子节点
        
        // 如果左子节点大于根
        if (left < n && arr[left] > arr[largest])
            largest = left;
        
        // 如果右子节点大于当前最大值
        if (right < n && arr[right] > arr[largest])
            largest = right;
        
        // 如果最大值不是根
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;
            
            // 递归地调整受影响的子树
            heapify(arr, n, largest);
        }
    }

    // 主函数,执行堆排序
    public static void heapSort(int[] arr) {
        int n = arr.length;
        
        // 构建初始大顶堆
        for (int i = n / 2 - 1; i >= 0; i--)
            heapify(arr, n, i);
        
        // 一个个从堆顶取出元素
        for (int i = n - 1; i > 0; i--) {
            // 移动当前根到数组末尾
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            
            // 调整剩下的堆
            heapify(arr, i, 0);
        }
    }

    public static void main(String[] args) {
        int[] arr = {12, 11, 13, 5, 6, 7};
        heapSort(arr);
        System.out.println("Sorted array: ");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}
相关推荐
祖力555 小时前
数据结构的基本概念与单向链表(链表数据类型构造、创建、头插、尾插、头删、尾删)
数据结构·链表
大明者省6 小时前
WSL2 Ubuntu22.04 GPU训练环境配置指南
人工智能·算法·计算机视觉
嘻哈∠※7 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_7987 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander2588 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅8 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
Shell运维手记8 小时前
Linux 常用基础命令学习笔记
linux·运维·笔记·学习·算法·github
杨航 AI8 小时前
O(n log n):线性对数原理拆解 这个是排序算法的黄金复杂度之一。
算法·排序算法
船厂电气自动化ai大模型9 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
旖旎夜光9 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口