java 数据结构之堆排序(HeapSort)详解及实例

Java 数据结构之堆排序(HeapSort)详解及实例

什么是堆排序

堆排序是一种树形选择排序,它的特点是不需要建立临时数组存放已排序的元素,而是直接在原数组上进行排序,因此空间复杂度比较小,时间复杂度为 $O(nlogn)$。

堆排序中需要用到的数据结构是堆,它是一种特殊的二叉树。堆分为大根堆和小根堆,大根堆满足任何一个非叶子节点的值都不小于其子节点的值,小根堆则相反,任何一个非叶子节点的值都不大于其子节点的值。

堆排序的算法步骤

  1. 将待排序的序列构建成一个大根堆或小根堆。
  2. 将堆顶元素(最大值或最小值)与末尾元素交换,从而将最大值或最小值放到了末尾。
  3. 将剩余的序列重新构建成一个堆。
  4. 重复步骤 2 和步骤 3,直到整个序列排序完成。

Java 代码实现

我们以使用大根堆进行从小到大排序为例,以下为 Java 代码实现:

public static void heapSort(int[] arr) {
    int len = arr.length;

    // 构建大根堆
    for (int i = len / 2 - 1; i >= 0; i--) {
        adjustHeap(arr, i, len);
    }

    // 交换堆顶元素到末尾
    for (int i = len - 1; i > 0; i--) {
        swap(arr, 0, i);
        adjustHeap(arr, 0, i);
    }
}

private static void adjustHeap(int[] arr, int i, int len) {
    int temp = arr[i];
    for (int k = 2 * i + 1; k < len; k = 2 * k + 1) {
        if (k + 1 < len && arr[k] < arr[k + 1]) {
            k++;
        }
        if (arr[k] > temp) {
            arr[i] = arr[k];
            i = k;
        } else {
            break;
        }
    }
    arr[i] = temp;
}

private static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

其中, adjustHeap 方法是用于调整堆的方法, swap 方法是交换元素的方法。

示例说明

以下为两个示例说明:

示例一

对数组 [4, 6, 8, 5, 9] 进行从小到大排序。

构建大根堆:

    4
  /   \
6      8

/ \
5 9

第一次交换堆顶元素到末尾:

    9
  /   \
6      8

/ \
5 4

重新构建堆:

    6
  /   \
5      8

/ \
4 9

第二次交换堆顶元素到末尾:

    8
  /   \
5      6

/ \
4 9

重新构建堆:

    6
  /   \
5      4

第三次交换堆顶元素到末尾:

    5
  /   \
4      6

重新构建堆:

    4

排序完成,数组变成了 [4, 5, 6, 8, 9]

示例二

对数组 [8, 7, 6, 5, 4, 3, 2, 1] 进行从小到大排序。

构建大根堆:

    8
  /   \
7      6

/ \ / \
5 4 3 2
/
1

第一次交换堆顶元素到末尾:

    1
  /   \
7      6

/ \ / \
5 4 3 2
/
8

重新构建堆:

    7
  /   \
5      6

/ \ / \
1 4 3 2
/
8

第二次交换堆顶元素到末尾:

    2
  /   \
5      6

/ \ / \
1 4 3 7
/
8

重新构建堆:

    6
  /   \
5      4

/ \ / \
1 2 3 7
/
8

第三次交换堆顶元素到末尾:

    3
  /   \
5      4

/ \ / \
1 2 6 7
/
8

重新构建堆:

    5
  /   \
1      4

/ \ / \
3 2 6 7
/
8

第四次交换堆顶元素到末尾:

    4
  /   \
1      2

/ \ / \
3 5 6 7
/
8

重新构建堆:

    3
  /   \
1      2

/ \ / \
4 5 6 7
/
8

第五次交换堆顶元素到末尾:

    2
  /   \
1      3

/ \ / \
4 5 6 7
/
8

重新构建堆:

    1
  /   \
4      3

/ \ / \
2 5 6 7
/
8

第六次交换堆顶元素到末尾:

    1
  /   \
2      3

/ \ / \
4 5 6 7
/
8

重新构建堆:

    2
  /   \
4      3

/ \ / \
5 1 6 7
/
8

第七次交换堆顶元素到末尾:

    1
  /   \
4      3

/ \ / \
5 2 6 7
/
8

重新构建堆:

    4
  /   \
5      3

/ \ / \
1 2 6 7
/
8

排序完成,数组变成了 [1, 2, 3, 4, 5, 6, 7, 8]

总结

堆排序相对于其他排序算法来说,其代码实现比较简单,空间复杂度比较小,时间复杂度较优秀。但是由于堆排序的算法思路和数组中数据的存储方式不同于其他排序算法,所以有时候可能会有一些不易于理解的地方。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java 数据结构之堆排序(HeapSort)详解及实例 - Python技术站

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

相关文章

  • JavaScript数据结构之广义表的定义与表示方法详解

    JavaScript数据结构之广义表的定义与表示方法详解 什么是广义表 广义表是一种包含了无数元素的数据结构,可以是元素或者嵌套的子表。广义表可以表示为: $\quad\quad\quad GL = (a_0,a_1,…,a_n)$ 其中$a_i$可以是元素或者一个子表,如果$a_i$为一个子表,那么$a_i$本身也是一个广义表。广义表中,第一个元素$a…

    数据结构 2023年5月17日
    00
  • 如何使用C语言实现平衡二叉树数据结构算法

    使用C语言实现平衡二叉树数据结构算法可以分为以下几个步骤: 第一步:了解平衡二叉树 平衡二叉树是一种二叉搜索树,它具有以下特点: 高度平衡:每个节点的左右子树的高度差不能超过1。 有序性:对于任意一个节点,它的左子树中的所有节点都小于它,它的右子树中的所有节点都大于它。 平衡二叉树的优点在于它的查找、插入和删除操作都可以在O(log n)的时间内完成,比较快…

    数据结构 2023年5月17日
    00
  • python数据结构之二叉树的统计与转换实例

    下面是针对“python数据结构之二叉树的统计与转换实例”的详细讲解攻略: 什么是二叉树 二叉树指的是一种树状结构,具有如下特点: 每个节点最多有两个子节点,分别为左子节点和右子节点 左子节点的值比父节点小,右子节点的值比父节点大 二叉树可以是空树,也可以是非空树。 二叉树的遍历 在对二叉树进行操作时,需要对其节点进行遍历。二叉树的遍历方式一般有以下三种: …

    数据结构 2023年5月17日
    00
  • Java数据结构之二叉排序树的实现

    Java数据结构之二叉排序树的实现 二叉排序树(Binary Sort Tree)是一种特殊的二叉树结构,它的每个结点都包含一个关键字,并满足以下性质: 左子树中所有结点的关键字都小于根结点的关键字; 右子树中所有结点的关键字都大于根结点的关键字; 左右子树也分别为二叉排序树。 这种结构有助于实现快速的查找、插入和删除操作。在此,我们将展示一种实现二叉排序树…

    数据结构 2023年5月17日
    00
  • C语言进阶数据的存储机制完整版

    C语言进阶数据的存储机制完整版攻略 1. 前言 C语言是一门高度可控的语言,其中其数据的存储机制是必须掌握的基础知识点。本文介绍了C语言数据存储的机制,包括变量在内存中的分配、指针的应用及结构体的组织等内容,旨在帮助读者掌握C语言中的数据存储机制。 2. 变量在内存中的分配 变量在内存中的分配既涉及到内存的分配可操作性,也涉及到相应的存储结构。 2.1. 变…

    数据结构 2023年5月17日
    00
  • 「学习笔记」数位 DP

    「学习笔记」数位 DP 意义不大的题不写了。 点击查看目录 目录 「学习笔记」数位 DP 概述 例题 P2657 [SCOI2009] windy 数 思路 代码 P4317 花神的数论题 思路 P4124 [CQOI2016]手机号码 思路 代码 haha数 题意 思路 代码 0和1的熟练 题意 思路 代码 苍与红的试炼 题意 思路 代码 概述 数位 DP…

    算法与数据结构 2023年4月17日
    00
  • C语言数据结构实例讲解单链表的实现

    C语言数据结构实例讲解单链表的实现 单链表是一种线性的数据结构,它由一系列节点组成,每个节点都包含一个数据域和一个指向下一个节点的指针域。单链表常用于需要频繁插入删除元素的场景中。 单链表的数据结构设计 在C语言中,我们可以使用结构体来定义单链表的节点: typedef struct node { int data; // 数据域 struct node* …

    数据结构 2023年5月17日
    00
  • Java数据结构之有向图的拓扑排序详解

    下面我将为您详细讲解“Java数据结构之有向图的拓扑排序详解”的完整攻略。 拓扑排序概述 拓扑排序是一种常见的有向无环图(DAG)的排序方法,该算法将DAG图中所有节点排序成一个线性序列,并且使得所有的依赖关系都满足从前向后的顺序关系。一般来说,DAG图的所有节点可以表示为一个任务依赖关系,而拓扑排序则可以对这些任务进行排序,确保每个任务在它所依赖的任务之后…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部