堆排序基础与实践:如安在Java中实现堆排序

打印 上一主题 下一主题

主题 684|帖子 684|积分 2052

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目次
一、堆排序的基本原理
二、堆排序的实现步骤
三、堆排序的时间复杂度和空间复杂度
四、堆排序的工作流程
五、堆排序的优缺点
六、堆排序的应用场景


堆排序(Heap Sort)是一种基于堆数据结构的排序算法。堆是一种特别的完全二叉树,堆排序使用堆的性质通过一系列操纵将数组元素按升序或降序排列。堆排序的时间复杂度为 O(n log n),是一种不稳固的排序算法,且其空间复杂度为 O(1),因此在某些场景下非常有用。
一、堆排序的基本原理

堆排序的核心是堆(Heap)这一数据结构,堆有两种情势:
(1)最大堆(Max-Heap):每个节点的值大于或等于其子节点的值,根节点的值是整个堆的最大值。
(2)最小堆(Min-Heap):每个节点的值小于或等于其子节点的值,根节点的值是整个堆的最小值。
堆排序一般使用最大堆来排序数组。堆排序的过程可以分为两个重要步骤:
(1)构建最大堆:将无序数组转换成最大堆。
(2)排序过程:反复将堆顶元素(最大值)与当前堆的末了一个元素互换,然后调整堆,直到堆中只剩下一个元素。
二、堆排序的实现步骤

(1)构建最大堆:起首将输入的无序数组构造成最大堆。此时数组中的最大元素位于根节点。
(2)互换堆顶元素与末了一个元素:将堆顶元素与堆的末了一个元素互换,并减小堆的有用元素数目。
(3)堆化:将根节点与其子节点进行比较,调整堆的结构,使其重新满足最大堆的性质。
(4)重复步骤2和3:直到堆的有用元素数目为1,整个数组已经排序完成。
三、堆排序的时间复杂度和空间复杂度

(1)时间复杂度:构建最大堆的时间复杂度是 O(n),而每次堆化的时间复杂度是 O(log n),因此总的时间复杂度为 O(n log n)。
(2)空间复杂度:堆排序是原地排序算法,因此其空间复杂度为 O(1)。四、堆排序的Java实现
下面是堆排序的Java实当代码:
  1. public class HeapSort {
  2.     // 堆化过程,保证以i为根的子树满足堆的性质
  3.     private static void heapify(int[] arr, int n, int i) {
  4.         int largest = i;  // 初始化最大值为根节点
  5.         int left = 2 * i + 1;  // 左子节点的位置
  6.         int right = 2 * i + 2;  // 右子节点的位置
  7.         // 如果左子节点大于根节点
  8.         if (left < n && arr[left] > arr[largest]) {
  9.             largest = left;
  10.         }
  11.         // 如果右子节点大于当前最大值
  12.         if (right < n && arr[right] > arr[largest]) {
  13.             largest = right;
  14.         }
  15.         // 如果最大值不是根节点,交换并继续堆化
  16.         if (largest != i) {
  17.             int temp = arr[i];
  18.             arr[i] = arr[largest];
  19.             arr[largest] = temp;
  20.             // 递归堆化受影响的子树
  21.             heapify(arr, n, largest);
  22.         }
  23.     }
  24.     // 堆排序主函数
  25.     public static void heapSort(int[] arr) {
  26.         int n = arr.length;
  27.         // 构建最大堆
  28.         for (int i = n / 2 - 1; i >= 0; i--) {
  29.             heapify(arr, n, i);
  30.         }
  31.         // 逐步将堆顶元素与最后一个元素交换,并调整堆
  32.         for (int i = n - 1; i >= 1; i--) {
  33.             // 将堆顶元素与当前未排序部分的最后一个元素交换
  34.             int temp = arr[0];
  35.             arr[0] = arr[i];
  36.             arr[i] = temp;
  37.             // 调整堆
  38.             heapify(arr, i, 0);
  39.         }
  40.     }
  41.     // 打印数组
  42.     private static void printArray(int[] arr) {
  43.         for (int i = 0; i < arr.length; i++) {
  44.             System.out.print(arr[i] + " ");
  45.         }
  46.         System.out.println();
  47.     }
  48.     public static void main(String[] args) {
  49.         int[] arr = {4, 10, 3, 5, 1};
  50.         System.out.println("Original array:");
  51.         printArray(arr);
  52.         heapSort(arr);
  53.         System.out.println("Sorted array:");
  54.         printArray(arr);
  55.     }
  56. }
复制代码
四、堆排序的工作流程

让我们通过一个简朴的例子来理解堆排序的工作流程。
1. 构建最大堆
假设我们有一个数组 arr = [4, 10, 3, 5, 1]。
(1)初始数组:[4, 10, 3, 5, 1]
(2)构建最大堆的过程中,我们从 i = n/2 - 1 开始,依次调整每个节点,直到根节点。
(3)调整后的堆:[10, 5, 3, 4, 1],此时堆顶的元素是最大值。
2. 排序过程
互换堆顶元素与末了一个元素,并调整堆。
(1)第一次互换:互换堆顶和末了一个元素后,数组变为:[1, 5, 3, 4, 10]。然后对剩余元素进行堆化,调整后的堆是:[5, 4, 3, 1, 10]。
(2)第二次互换:互换堆顶和倒数第二个元素,数组变为:[1, 4, 3, 5, 10],调整后的堆是:[4, 1, 3, 5, 10]。
(3)第三次互换:互换堆顶和倒数第三个元素,数组变为:[3, 1, 4, 5, 10],调整后的堆是:[3, 1, 4, 5, 10]。
(4)第四次互换:互换堆顶和倒数第四个元素,数组变为:[1, 3, 4, 5, 10],此时只有一个元素剩下,排序完成。
最终,数组变为升序排列:[1, 3, 4, 5, 10]。
五、堆排序的优缺点

长处:
(1)时间复杂度稳固:无论输入数据如何,堆排序的时间复杂度始终为 O(n log n),不受数据分布影响。
(2)空间复杂度低:堆排序是原地排序算法,其空间复杂度为 O(1),无需额外的辅助空间。
(3)得当大数据处置惩罚:由于堆排序的时间复杂度稳固且不依赖于数据的初始状态,它实用于大数据量的排序。
缺点:
(1)不是稳固排序:堆排序不包管相称元素的相对顺序,因此不实用于需要稳固排序的场景。
(2)常数因素较大:虽然堆排序的时间复杂度是 O(n log n),但其常数因素较大,通常比快速排序和归并排序要慢,尤其在处置惩罚小数据集时。
六、堆排序的应用场景

(1)优先队列实现:堆可以用来实现优先队列,特别是在需要频仍获取最大或最小值的场景中(例如,Dijkstra算法、Huffman编码)。
(2)外部排序:当数据量过大,不能全部加载到内存时,堆排序可以有用地对外部存储的海量数据进行排序。
总结
堆排序是一种基于堆数据结构的排序算法,具有 O(n log n) 的时间复杂度和 O(1) 的空间复杂度。尽管堆排序是一个不稳固的排序算法,但其高效性和原地排序特性使它在某些特定场景中非常有用,尤其是在需要频仍访问最大值或最小值的应用中。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

星球的眼睛

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表