Java代码为例讲解堆的性质和基本操作以及排序方法

Java代码为例讲解堆的性质和基本操作以及排序方法

什么是堆?

堆(Heap)是一种基于二叉树的数据结构,常用于排序和优先级队列中。堆又分为大根堆和小根堆,大根堆满足任意节点的值都不大于其父节点的值,小根堆则相反。这里我们以大根堆为例。

堆的基本操作

插入元素

堆的插入操作是往堆中添加新值并保证堆的性质不变。具体实现如下:

public void insert(int value) {
    if (size == maxsize)
        return;
    heap[size] = value;
    int current = size;
    while (heap[current] > heap[parent(current)]) {
        swap(current, parent(current));
        current = parent(current);
    }
    size++;
}

其中,size为当前堆中元素数量,maxsize为堆的最大容量,heap为堆的数组,parent(current)为当前节点的父节点,swap(current, parent(current))为交换当前节点和父节点。

删除元素

堆的删除操作是删除堆的根节点并保持堆的性质。具体实现如下:

public int delete() {
    int popped = heap[0];
    heap[0] = heap[--size];
    heapify(0);
    return popped;
}

public void heapify(int index) {
    int largest = index;
    int left = leftChild(index);
    int right = rightChild(index);
    if (left < size && heap[left] > heap[largest])
        largest = left;
    if (right < size && heap[right] > heap[largest])
        largest = right;
    if (largest != index) {
        swap(index, largest);
        heapify(largest);
    }
}

其中,popped为删除的元素,leftChild(index)为当前节点的左侧子节点,rightChild(index)为当前节点的右侧子节点。

建立堆

如果给定的无序数组需要排序,可以先将其构建成一个堆再进行排序。建立堆的过程称为堆化。具体实现如下:

public void buildHeap(int[] arr) {
    if (arr.length > maxsize)
        return;
    size = arr.length;
    heap = Arrays.copyOf(arr, maxsize);
    for (int i = (size - 2) / 2; i >= 0; i--) {
        heapify(i);
    }
}

其中,arr为给定的数组,Arrays.copyOf(arr, maxsize)为将arr数组复制到大小为maxsize的heap数组中,(size - 2) / 2为最后一个非叶子节点的下标。

排序方法

堆排序

堆排序以大根堆为例,其基本思路是先将待排序序列构建成一个大根堆,再不断将堆的根节点和堆的最后一个非空节点交换,然后将堆的大小减1,再进行调整,直到堆的大小为1为止。

具体实现如下:

public void heapSort(int[] arr) {
    buildHeap(arr);
    for (int i = size-1; i > 0; i--) {
        swap(0, i);
        size--;
        heapify(0);
    }
}

其中,buildHeap(arr)为构建堆,swap(0, i)为交换第一个元素(堆的根节点)和第i个元素。

示例1:

假设给定一个无序序列[4, 10, 3, 5, 1, 8, 9],进行堆排序后的结果应该是[1, 3, 4, 5, 8, 9, 10]。

int[] arr = {4, 10, 3, 5, 1, 8, 9};
HeapSort hs = new HeapSort();
hs.heapSort(arr);
System.out.println(Arrays.toString(arr));

输出结果为[1, 3, 4, 5, 8, 9, 10]。

示例2:

假设给定一个无序序列[6, 3, 7, 8, 1, 4, 5, 9, 2],求第K大的数,这里以K=2为例。

int[] arr = {6, 3, 7, 8, 1, 4, 5, 9, 2};
HeapSort hs = new HeapSort();
hs.buildHeap(arr);
for (int i = 0; i < 2; i++) {
    hs.delete();
}
System.out.println(hs.delete());

输出结果为8,即第2大的数为8。

总结

堆是一种基于二叉树的数据结构,常用于排序和优先级队列中。堆的基本操作包括插入元素、删除元素和建立堆,其中建立堆是进行堆排序的先决条件。堆排序的基本思路是先将待排序序列构建成一个大根堆,再不断将堆的根节点和堆的最后一个非空节点交换,然后将堆的大小减1,再进行调整,直到堆的大小为1为止。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java代码为例讲解堆的性质和基本操作以及排序方法 - Python技术站

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

相关文章

  • Springboot集成spring data elasticsearch过程详解

    下面是详细讲解“Springboot集成springdataelasticsearch过程详解”的完整攻略: 1. 确认环境和依赖 首先,我们需要确认一下环境和需要的依赖。假设我们已经有了一个Spring Boot项目,并且使用了Maven作为我们的构建工具。在pom.xml文件中,我们需要添加以下依赖: <dependency> <gro…

    Java 2023年5月15日
    00
  • Spring Data JPA分页复合查询原理解析

    Spring Data JPA分页复合查询原理解析 在使用 Spring Data JPA 的过程中,分页和复合查询是经常用到的功能。本文将详细讲解 Spring Data JPA 分页和复合查询的原理,同时给出两个示例进行演示。 分页原理 Spring Data JPA 的分页功能基于 Spring Framework 的 PagingAndSorting…

    Java 2023年5月20日
    00
  • Mysql到Elasticsearch高效实时同步Debezium实现

    关于Mysql到Elasticsearch高效实时同步Debezium实现的攻略,我可以提供如下具体步骤: 准备工作 安装Mysql、Elasticsearch、Kibana和Debezium Connector并设置好它们的环境变量,确保能正常运行它们。 开启binlog以便Debezium捕获Mysql的数据变更,具体可以在Mysql中修改配置文件my.…

    Java 2023年5月20日
    00
  • Java的Struts框架报错“ServletException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“ServletException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中没有正确配置,则可能会出现此错误。在这种情况下,检查文件以解决此问题。 代码错误:如果代码中存在错误,则可能会出现此错误。在这种情况下,需要检查代码以解决此问题。 以下是两个实例: 例 1 如果配置文件中没有正确配置…

    Java 2023年5月5日
    00
  • java 线程池keepAliveTime的含义说明

    当我们使用Java中的线程池时,线程池使用keepAliveTime参数来确定当线程池中的线程处于空闲状态时,我们希望线程在终止之前可以保持的时间量。如果一段时间内没有任务需要执行,线程则会被清除,以帮助线程池节省资源。 具体来说,keepAliveTime表示在线程池处于空闲状态且当前线程数量超过corePoolSize时,空闲线程等待新任务的最长时间。在…

    Java 2023年5月20日
    00
  • Tomcat启动核心流程示例详解

    Tomcat启动核心流程示例详解 简介 Tomcat 是一个开源的 Web 应用服务器,是最流行的 Java Web 应用服务器之一。在开发和部署 Web 应用时,Tomcat 的启动过程是非常重要的,因为它决定了 Web 应用的运行状态以及访问方式等重要因素。下面将详细讲解 Tomcat 启动的核心流程,并提供两个示例来帮助理解。 启动流程 Tomcat …

    Java 2023年5月19日
    00
  • 基于Java中字符串内存位置详解

    基于Java中字符串内存位置详解攻略 什么是Java字符串 在Java中,字符串(String)是一种对象类型,可以用来存储和操作文本数据。Java中的字符串是不可变的,也就是说,一旦创建,字符串对象的值就无法改变。 例如,我们可以使用以下代码来创建一个字符串对象: String str = "Hello, world!"; Java字符…

    Java 2023年5月26日
    00
  • 关于properties配置文件的加密方式

    关于properties配置文件的加密方式,可以采用Jasypt这个Java加密工具来实现。 具体步骤如下: 导入Jasypt的依赖包,可以在Maven中添加以下配置: <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>ja…

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