JAVA堆排序算法的讲解

yizhihongxing

JAVA堆排序算法的讲解

算法简介

堆排序(Heap Sort)是一种选择排序,它的主要思想是将待排序序列构建成一个大顶堆或小顶堆,然后将堆顶元素与最后一个元素交换位置,再对剩余 n - 1 个元素进行同样的操作,依次类推,直到整个序列有序。

堆排序的时间复杂度为 O(nlogn),是一种比较高效的排序算法。

算法步骤

  1. 对待排序的序列进行堆的构建,构建出一个大顶堆或小顶堆;
  2. 构建出堆后,堆顶元素一定是最大或最小的元素,将其与序列的最后一个元素进行交换;
  3. 排除掉已经排好序的最后一个元素,对剩余元素重新构建堆,重复步骤2和3,直到所有元素都已经排好序。

代码实现

JAVA 代码实现

/**
 * 堆排序算法
 * 时间复杂度:O(nlogn)
 */
public class HeapSort {

    public static void sort(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--) {
            swap(arr, 0, i);
            heapify(arr, i, 0);
        }
    }

    /**
     * 将以i为根节点的子树调整成大顶堆
     * @param arr 数组
     * @param n 数组长度
     * @param i 根节点位置
     */
    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) {
            swap(arr, i, largest);
            heapify(arr, n, largest);
        }
    }

    /**
     * 交换数组中的两个元素
     * @param arr 数组
     * @param i 元素1的位置
     * @param j 元素2的位置
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

Python 代码实现

def heap_sort(arr):
    n = len(arr)

    # 构建大顶堆,从最后一个非叶子节点开始向下调整
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    # 将堆顶元素与序列最后一个元素交换位置,然后对剩余元素重新构建堆
    for i in range(n - 1, 0, -1):
        arr[0], arr[i] = arr[i], arr[0]
        heapify(arr, i, 0)

def heapify(arr, n, i):
    largest = i # 根节点
    left = 2 * i + 1 # 左子节点
    right = 2 * i + 2 # 右子节点

    # 找到最大的节点
    if left < n and arr[left] > arr[largest]:
        largest = left
    if right < n and arr[right] > arr[largest]:
        largest = right

    # 如果最大节点不是根节点,那么把最大节点与根节点交换,然后继续向下递归调整
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

示例

示例1

排序前的数组:[5, 3, 8, 4, 7, 2, 6, 1]

排序后的数组:[1, 2, 3, 4, 5, 6, 7, 8]

示例2

排序前的数组:[99, 0, 33, 46, 12, 78, 21, 5]

排序后的数组:[0, 5, 12, 21, 33, 46, 78, 99]

总结

堆排序算法是一种高效的排序算法,适用于大规模数据的排序。它通过构建大顶堆或小顶堆,实现了对序列的快速排序。堆排序可以通过数组实现,也可以通过树实现。

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

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

相关文章

  • Struts2配置文件中使用通配符的方法(三种形式)

    使用通配符在Struts2配置文件中可以方便地定义多个相似的Action或者Interceptor,以及进行全局的配置。 在Struts2的配置文件中,有三种形式可以使用通配符,分别如下: 使用“”号通配符 例如:<package name=”default” extends=”struts-default”> <action name=”…

    Java 2023年5月20日
    00
  • 解决idea2020.1找不到程序包和符号的问题

    问题背景: 在使用IntelliJ IDEA 2020.1时,有时会遇到找不到程序包和符号的问题。这个问题可能是由于项目依赖导致的,也可能是由于代码中的语法错误导致的。 解决方案: 检查项目依赖 首先,需要检查项目的依赖是否正确。在项目的pom.xml文件(Maven项目)或build.gradle文件(Gradle项目)中查看所依赖的库是否正确且版本是否匹…

    Java 2023年5月20日
    00
  • JSP页面中文传递参数使用escape编码

    JSP页面中文传递参数使用escape编码的完整攻略如下: 1. 什么是escape编码? escape编码是一种在传递URL参数时,将不安全字符转义成%xx的形式的编码方式。其中,XX是不安全字符在ASCII码表中相应的16进制数字。 2. escape编码的使用场景 在JSP页面中,如果我们需要传递中文参数给后台处理,如果我们不对这些中文参数进行编码,那…

    Java 2023年6月15日
    00
  • Spring Security表单配置过程分步讲解

    下面是关于Spring Security表单配置过程分步讲解的攻略,包含以下几个步骤: 引入Spring Security依赖 要使用Spring Security,需要在项目中引入相应的依赖。在Maven项目中,可以在pom.xml文件中添加以下依赖: <dependency> <groupId>org.springframewor…

    Java 2023年5月20日
    00
  • Java Cmd运行Jar出现乱码的解决方案

    请看以下完整攻略: Java Cmd运行Jar出现乱码的解决方案 很多Java程序员在用cmd运行jar包时,都会遇到乱码的问题。这主要是因为cmd默认编码是GBK而不是UTF-8,而jar包中的资源文件往往是UTF-8编码的。本文就为大家介绍几种解决方案。 方案一:修改Cmd编码为UTF-8 这种方式比较简单,只需要在cmd输入以下命令: chcp 650…

    Java 2023年5月20日
    00
  • SpringBoot整合SQLite数据库全过程

    下面我将为您详细讲解SpringBoot整合SQLite数据库的全过程,包括以下几个步骤: 导入SQLite依赖 配置SQLite数据源 创建实体类 创建DAO接口 创建Service层 创建Controller层 示例演示 1.导入SQLite依赖 在pom.xml文件中添加以下依赖: <dependency> <groupId>o…

    Java 2023年5月20日
    00
  • java多线程Future和Callable类示例分享

    标题:Java多线程Future和Callable类示例分享 什么是Java的Future和Callable类? 在Java多线程编程中,使用Future和Callable类可以方便地处理异步任务,也可以获取异步任务的结果。 Callable是一个函数式接口,它描述的是具有返回值的任务。可以通过实现Callable接口并实现它的call()方法来定义自己的任…

    Java 2023年5月19日
    00
  • Java超详细讲解三大特性之一的多态

    Java多态性 Java三大特性之一的多态,是Java面向对象编程的核心概念之一。本文将详细讲解Java多态性的基本概念、实现方法以及使用场景。 多态性的基本概念 多态性(Polymorphism)是指同一个方法名可以在不同的对象上有不同的实现方式,也可以理解为一种类型的普遍性和多样性。多态性分为两种类型: 静态多态性(编译时多态性):在编译期就可以确定具体…

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