堆排序算法的讲解及Java版实现

堆排序算法的讲解及Java版实现

目录

概述

堆排序(Heap Sort)是一种选择排序,它的平均时间复杂度为 O(nlogn),实用性较高。

堆排序的基本思想是:

  1. 将待排序的序列构建成一个大顶堆(或小顶堆);
  2. 此时,整个序列的最大值(或最小值)就是堆顶的根节点;
  3. 将其与末尾元素进行交换,此时末尾就为最大值(或最小值);
  4. 然后将剩下的 n-1 个元素重新构建成一个堆,继续进行交换操作,直到整个序列有序。

堆的实现

在堆排序中,我们需要用到堆的数据结构。堆实际上是一个完全二叉树,分为大顶堆和小顶堆。

  • 大顶堆:每个节点的值都大于或等于其左右子节点的值。
  • 小顶堆:每个节点的值都小于或等于其左右子节点的值。

实现堆的时候,我们可以用一维数组来表示。假设数组的下标从 1 开始,那么对于下标为 i 的节点:

  • 左节点索引为 i * 2;
  • 右节点索引为 i * 2 + 1;
  • 父节点索引为 i / 2。

堆排序的实现

堆排序算法的思路分成两个主要的过程:

  1. 将序列构建成堆;
  2. 将堆顶元素与末尾元素交换,并且重新将剩下的元素构建成堆,重复操作直到整个序列有序。

具体实现过程:

  1. 构建大根堆(升序排序)或小根堆(降序排序),即使每个非叶子节点的值都大于或等于(或小于或等于)其子节点的值。

    1. 从后向前遍历数组,对于当前索引为 i 的元素:
      1. 将其与左右子节点中较大的那一个交换位置,直到满足堆的定义。
    2. 当整个数组都构建完毕后,堆顶元素就是最大值(或最小值)。
  2. 将堆顶元素与末尾元素进行交换,并且重新将其余元素构建成堆。

    1. 将堆顶元素与末尾元素互换位置,此时末尾就是数组中的最大值(或最小值)。
    2. 对于前面 n-1 个元素重新进行构建堆的操作。

重复上述步骤,直到整个序列有序。

Java版实现示例

public class HeapSort {
    public static void sort(int[] arr) {
        // 构建大根堆
        buildHeap(arr, arr.length - 1);
        // 从后向前遍历数组,依次将堆顶元素与末尾元素交换,并重新构建堆
        for (int i = arr.length - 1; i >= 1; i--) {
            swap(arr, 0, i); // 将堆顶元素与末尾元素交换位置
            heapify(arr, 0, i - 1); // 重新构建堆
        }
    }

    // 构建大根堆
    private static void buildHeap(int[] arr, int end) {
        for (int i = (end - 1) / 2; i >= 0; i--) {
            heapify(arr, i, end);
        }
    }

    // 以节点 i 为根的子树重新构建大根堆
    private static void heapify(int[] arr, int i, int end) {
        int left = i * 2 + 1; // 左子节点索引
        int right = i * 2 + 2; // 右子节点索引
        int max = i; // 堆的最大节点索引
        // 找到堆中最大的节点
        if (left <= end && arr[left] > arr[max]) {
            max = left;
        }
        if (right <= end && arr[right] > arr[max]) {
            max = right;
        }
        if (max != i) { // 若最大节点不是当前节点,就将其交换位置
            swap(arr, i, max);
            heapify(arr, max, end); // 对以 max 为根的子树进行堆化操作
        }
    }

    // 交换数组中下标为 i 和 j 的元素
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

示例一:对数组 {7, 6, 5, 4, 3, 2, 1} 进行堆排序(升序排列)

int[] arr = {7, 6, 5, 4, 3, 2, 1};
HeapSort.sort(arr);
System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7]

示例二:对数组 {-1, 0, 3, 5, 2, 1} 进行堆排序(降序排列)

int[] arr = {-1, 0, 3, 5, 2, 1};
HeapSort.sort(arr);
System.out.println(Arrays.toString(arr)); // 输出 [5, 3, 2, 1, 0, -1]

以上就是堆排序算法的讲解及Java版实现的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:堆排序算法的讲解及Java版实现 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 关于Kafka消息队列原理的总结

    关于Kafka消息队列原理的总结,我将分以下几个方面讲解。 简介 Kafka是一种基于发布/订阅模式的消息队列系统,它主要用于处理大规模的消息数据流,支持高吞吐率、可扩展性和容错性。具体来说,在Kafka中,消息被分为若干个主题(Topic),每个主题包含若干个分区(Partition),每个分区又包含若干个消息(Message)。Kafka的消息生产者(P…

    Java 2023年5月20日
    00
  • java多线程关键字final和static详解

    Java多线程关键字final和static详解 在Java中,final和static是常用的关键字之一,它们不仅在单线程中有用,而且在多线程环境中也起到了非常重要的作用。本文将详细介绍final和static的使用场景及每个场景的一些细节问题。 final关键字 final关键字表示最终的,不可更改的。因此,final变量一旦被初始化赋值以后,就不能再更…

    Java 2023年5月19日
    00
  • Java异常类型及处理

    Java异常类型及处理攻略 异常定义 在程序执行时,如果出现某种错误或异常,则会产生异常。Java中所有的异常信息都是用异常类的形式传递的。在Java中,所有异常都是派生于Throwable类(它是 Java 语言中所有错误或异常的超类)的一个子类。它既包括异常(Exception)也包括错误(Error),它们有各自的特点: Exception Excep…

    Java 2023年5月26日
    00
  • 从0开始学习大数据之java spark编程入门与项目实践

    从0开始学习大数据之Java Spark编程入门与项目实践攻略 前言 在大数据时代,数据量和数据处理的复杂性不断增加,需要更加高效和灵活的处理方式。Apache Spark作为当前最流行的大数据处理框架之一,优化了Hadoop MapReduce的不足,支持复杂的数据处理,具有高效、可扩展、易用、友好的API等特点,因此成为很多企业和个人的选择。本文将详细介…

    Java 2023年5月19日
    00
  • SpringBoot中时间类型 序列化、反序列化、格式处理示例代码

    下面我就来为您详细讲解“SpringBoot中时间类型 序列化、反序列化、格式处理示例代码”的完整攻略。 1. 背景介绍 在实际开发中,我们经常会遇到时间类型的序列化、反序列化、格式处理问题,SpringBoot在处理时间类型时提供了很多便利,本文将介绍SpringBoot中时间类型的序列化、反序列化、格式处理示例代码。 2. 时间类型的序列化 在Sprin…

    Java 2023年5月20日
    00
  • Spring Boot自定义 Starter并推送到远端公服的详细代码

    以下是详细讲解 Spring Boot 自定义 Starter 并推送到远端公服的详细攻略,过程中包含两个示例。 1. 确定自定义 Starter 的功能和作用 在开发自定义 Starter 之前,需要先确定该 Starter 的功能和作用。例如,自定义 Starter 可以用来统一管理日志、配置数据源、集成第三方组件等。 在这个例子中,我们将自定义 Sta…

    Java 2023年6月2日
    00
  • JS+JSP通过img标签调用实现静态页面访问次数统计的方法

    使用JS+JSP通过img标签调用实现静态页面访问次数统计的方法,大致分为以下几个步骤: 创建一个动态生成图片的JSP程序,该程序用来统计访问次数并返回一张透明的1×1像素的PNG图片。 <%@ page language="java" contentType="image/png; charset=UTF-8"…

    Java 2023年6月15日
    00
  • hibernate属性级别注解实例代码

    让我为您详细讲解一下使用Hibernate属性级别注解的实例代码攻略。 什么是属性级别注解 在Hibernate中,可以使用注解来映射实体类的属性和表中的字段。属性级别注解是指直接在实体类属性上使用的注解,可以指定字段名、数据类型、是否允许为空、默认值等属性。使用属性级别注解可以让开发者更方便地管理实体类属性与数据库字段之间的映射关系。 使用属性级别注解 我…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部