当前位置: 首页 > news >正文

Java手写堆排序(Heap Sort)和案例

Java手写堆排序(Heap Sort)

1. 思维导图

下面是使用Mermaid代码绘制的思维导图,用于解释堆排序算法的实现思路原理:

建立最大堆
交换堆顶和最后一个元素
维护最大堆性质
是否完成排序?
结束

2. 手写堆排序的必要性

堆排序是一种高效的排序算法,它的时间复杂度为O(nlogn),具有以下几个方面的优势:

  • 相对于其他基于比较的排序算法(如快速排序、归并排序),堆排序是一种原地排序算法,不需要额外的辅助空间;
  • 堆排序是稳定的排序算法,不会改变相同元素之间的顺序;
  • 堆排序在最坏情况下仍具有较好的性能,因此在一些对排序稳定性要求较高的场景中,堆排序是一个不错的选择。

3. 市场调研

据市场调研,堆排序在实际应用中广泛使用,特别是在以下场景中:

  • 大规模数据的排序:由于堆排序的时间复杂度较低且具备稳定性,因此在需要对大规模数据进行排序的场景中,堆排序是一种常用的选择;
  • 优先级队列:堆排序的基础是堆这种数据结构,而堆被广泛用于实现优先级队列。优先级队列是一种可以动态地插入和删除元素,并且每次操作都能高效地找到最大(或最小)值的数据结构,而堆正是实现这一特性的关键;
  • 排名统计:堆排序在一些需要对数据进行排名统计的场景中也有应用,例如按照成绩对学生进行排名、按照销售额对商品进行排名等。

4. 实现步骤

堆排序的实现步骤包括以下几个部分:

4.1 建立最大堆

首先,我们需要构建一个最大堆,以便后续的排序操作。建立最大堆的步骤如下:

  1. 从最底层的非叶子节点开始,逐层向上调整,使得每个节点都满足最大堆的性质;
  2. 对于当前节点,比较其与左右子节点的大小,如果存在比当前节点更大的子节点,则交换两者的位置;
  3. 重复上述比较和交换的步骤,直到当前节点满足最大堆的性质或成为叶子节点。

以下是建立最大堆的Java代码:

// 建立最大堆
public static void buildMaxHeap(int[] array, int length) {for (int i = length / 2 - 1; i >= 0; i--) {heapify(array, length, i);}
}

4.2 交换堆顶和最后一个元素

建立最大堆之后,最大堆的堆顶元素即为数组中的最大值。我们将堆顶元素与数组中的最后一个元素进行交换。

以下是交换堆顶和最后一个元素的Java代码:

// 交换堆顶和最后一个元素
public static void swap(int[] array, int i, int j) {int temp = array[i];array[i] = array[j];array[j] = temp;
}

4.3 维护最大当交换堆顶和最后一个元素后,我们需要维护最大堆的性质,以保证新的堆顶元素是剩下元素中的最大值。

维护最大堆的步骤如下:

  1. 将交换后的堆顶元素(原数组的最后一个元素)下沉到合适的位置,以满足最大堆的性质;
  2. 每次将当前节点与其子节点进行比较,如果存在比当前节点更大的子节点,则将其与其中较大的子节点进行交换;
  3. 重复上述比较和交换的步骤,直到当前节点满足最大堆的性质或成为叶子节点。

以下是维护最大堆的Java代码:

// 维护最大堆性质
public static void heapify(int[] array, int length, int i) {int largest = i;      // 当前节点int left = 2 * i + 1; // 左子节点int right = 2 * i + 2; // 右子节点// 如果左子节点比当前节点大if (left < length && array[left] > array[largest]) {largest = left;}// 如果右子节点比当前节点大if (right < length && array[right] > array[largest]) {largest = right;}// 如果最大值不是当前节点,交换它们的位置并继续调整if (largest != i) {swap(array, i, largest);heapify(array, length, largest);}
}

4.4 排序

在建立最大堆和维护最大堆的基础上,我们可以进行堆排序了。

堆排序的步骤如下:

  1. 通过调用建立最大堆的函数,构建一个最大堆;
  2. 从最后一个元素开始,依次将堆顶元素与当前元素进行交换,并缩小堆的范围以排除已排序的元素;
  3. 重复上述交换和缩小堆范围的操作,直到只剩下一个元素。

以下是堆排序的Java代码:

// 堆排序
public static void heapSort(int[] array) {int length = array.length;// 建立最大堆buildMaxHeap(array, length);// 从最后一个元素开始,依次交换堆顶和当前元素,并调整堆for (int i = length - 1; i >= 0; i--) {swap(array, 0, i);heapify(array, i, 0);}
}

5. 手写总结

堆排序是一种高效稳定的排序算法,适用于大规模数据的排序和优先级队列的实现。它的实现步骤包括建立最大堆、交换堆顶和最后一个元素、维护最大堆性质以及排序操作。通过合理地利用最大堆的性质,堆排序能够在O(nlogn)的时间复杂度下完成排序任务。

6. 拓展案例代码

按照成绩对学生进行排名

假设有一个学生列表,每个学生包含姓名和成绩两个属性。我们可以使用堆排序按照成绩对学生进行排名。

class Student {String name;int score;// 构造函数和其他方法省略...
}public static void heapSortByScore(Student[] students) {int length = students.length;// 建立最大堆,按照成绩进行比较buildMaxHeapByScore(students, length);// 从最后一个学生开始,依次交换堆顶和当前学生,并调整堆for (```java
int i = length - 1; i >= 0; i--) {swap(students, 0, i);heapifyByScore(students, i, 0);}
}// 建立最大堆,按照成绩进行比较
public static void buildMaxHeapByScore(Student[] students, int length) {for (int i = length / 2 - 1; i >= 0; i--) {heapifyByScore(students, length, i);}
}// 维护最大堆性质,按照成绩进行比较
public static void heapifyByScore(Student[] students, int length, int i) {int largest = i;int left = 2 * i + 1;int right = 2 * i + 2;if (left < length && students[left].score > students[largest].score) {largest = left;}if (right < length && students[right].score > students[largest].score) {largest = right;}if (largest != i) {swap(students, i, largest);heapifyByScore(students, length, largest);}
}// 交换两个学生的位置
public static void swap(Student[] students, int i, int j) {Student temp = students[i];students[i] = students[j];students[j] = temp;
}

使用示例:

Student[] students = new Student[5];
students[0] = new Student("Alice", 80);
students[1] = new Student("Bob", 75);
students[2] = new Student("Charlie", 90);
students[3] = new Student("David", 85);
students[4] = new Student("Eve", 70);heapSortByScore(students);for (Student student : students) {System.out.println(student.name + ": " + student.score);
}

输出结果:

Charlie: 90
Alice: 80
David: 85
Bob: 75
Eve: 70

按照成绩从高到低排名的结果就是Charlie、Alice、David、Bob、Eve。

这是一个基于堆排序的简单拓展案例,可以根据具体需求进行进一步的扩展和优化。希望对你有帮助!

http://www.lryc.cn/news/168343.html

相关文章:

  • Linux设备驱动模型之字符设备
  • Kafka3.0.0版本——消费者(自动提交 offset)
  • 【业务功能116】微服务-springcloud-springboot-Kubernetes集群-k8s集群-KubeSphere-公共服务 DNS
  • 马斯洛的动机与人格、需求层次理论
  • TCP/IP网络传输模型及协议
  • git 推送出现fatal: The remote end hung up unexpectedly解决方案
  • Hive内置函数字典
  • svg 知识点总结
  • 开源库源码分析:OkHttp源码分析(二)
  • 校园地理信息系统的设计与实现
  • Vulnhub实战-prime1
  • Scala学习笔记
  • 虹科分享 | 软件供应链攻击如何工作?如何评估软件供应链安全?
  • gRpc入门和springboot整合
  • 基于FPGA点阵显示屏设计-毕设
  • Rocky9.2基于http方式搭建局域网yum源
  • Android 串口通讯
  • 论如何在Android中还原设计稿中的阴影
  • Hadoop生态圈中的Flume数据日志采集工具
  • FFmpeg获取媒体文件的视频信息
  • io概述及其分类
  • 前端面试话术集锦第 14 篇:高频考点(React常考基础知识点)
  • UI/UX+前端架构:设计和开发高质量的用户界面和用户体验
  • 长尾关键词挖掘软件-免费的百度搜索关键词挖掘
  • React Native 环境配置(mac)
  • CAD for JS:VectorDraw web library 10.1004.1 Crack
  • 代码管理工具git1
  • 层次聚类分析
  • Jmeter性能实战之分布式压测
  • 学信息系统项目管理师第4版系列08_管理科学基础