【算法】堆排序的原理与Java实现

简介: 堆排序(Heap Sort)是一种基于堆数据结构的排序算法。堆是一种完全二叉树,其中父节点的值总是大于(或小于)其子节点的值。堆排序的基本思想是先将待排序的数组构建成一个最大堆(或最小堆),然后重复从堆顶取出最大(或最小)元素,放到已排序的部分,再调整剩余元素构建新的堆,直到所有元素都被放置到正确的位置。

一.堆排序原理


堆排序(Heap Sort)是一种基于堆数据结构的排序算法。堆是一种完全二叉树,其中父节点的值总是大于(或小于)其子节点的值。堆排序的基本思想是先将待排序的数组构建成一个最大堆(或最小堆),然后重复从堆顶取出最大(或最小)元素,放到已排序的部分,再调整剩余元素构建新的堆,直到所有元素都被放置到正确的位置。


堆排序的具体步骤如下:

1.构建最大堆(或最小堆):将待排序的数组看作是一个完全二叉树,并从最后一个非叶子节点开始,自底向上地调整每个节点,使其满足堆的性质。这一步骤保证了最大堆(或最小堆)的构建。

2.取出堆顶元素:将堆顶元素(最大元素或最小元素)与堆中最后一个元素交换位置,并将堆的大小减一。

3.调整堆:将堆顶元素下沉至合适的位置,保持堆的性质。这一步骤重新构建了最大堆(或最小堆)。

4.重复步骤2和步骤3,直到堆为空。


二.使用Java实现堆排序


public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {5, 2, 8, 3, 1};
        System.out.println("Before sorting:");
        printArray(arr);
        heapSort(arr);
        System.out.println("After sorting:");
        printArray(arr);
    }
    public static void heapSort(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--) {
            // 将堆顶元素与最后一个元素交换
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            // 调整堆,保持最大堆性质
            heapify(arr, i, 0);
        }
    }
    public static void heapify(int[] arr, int n, int i) {
        int largest = i; // 当前节点的索引
        int leftChild = 2 * i + 1; // 左子节点的索引
        int rightChild = 2 * i + 2; // 右子节点的索引
        // 如果左子节点大于父节点,更新最大节点的索引
        if (leftChild < n && arr[leftChild] > arr[largest]) {
            largest = leftChild;
        }
        // 如果右子节点大于父节点,更新最大节点的索引
        if (rightChild < n && arr[rightChild] > arr[largest]) {
            largest = rightChild;
        }
        // 如果最大节点不是当前节点,交换节点的位置并继续调整堆
        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            heapify(arr, n, largest);
        }
    }
    public static void printArray(int[] arr) {
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

以上代码使用堆排序算法对一个整数数组进行排序。heapSort方法实现了堆排序的逻辑,首先构建最大堆,然后重复从堆顶取出最大元素,放到已排序的部分,并调整剩余元素构建新的堆,直到所有元素都被放置到正确的位置。heapify方法用于调整堆,保持最大堆性质。


运行以上代码,将输出如下结果:

Before sorting:
5 2 8 3 1 
After sorting:
1 2 3 5 8

堆排序算法的时间复杂度为O(nlogn),其中n是数组的长度。它是一种不稳定的排序算法,适用于任何规模的数组。堆排序在实现上相对较复杂,但由于其在原地排序的特性,对于大规模数据的排序效果较好。

相关文章
|
1天前
|
存储 Java
JAVA并发编程AQS原理剖析
很多小朋友面试时候,面试官考察并发编程部分,都会被问:说一下AQS原理。面对并发编程基础和面试经验,专栏采用通俗简洁无废话无八股文方式,已陆续梳理分享了《一文看懂全部锁机制》、《JUC包之CAS原理》、《volatile核心原理》、《synchronized全能王的原理》,希望可以帮到大家巩固相关核心技术原理。今天我们聊聊AQS....
|
8天前
|
缓存 Java 编译器
JAVA并发编程volatile核心原理
volatile是轻量级的并发解决方案,volatile修饰的变量,在多线程并发读写场景下,可以保证变量的可见性和有序性,具体是如何实现可见性和有序性。以及volatile缺点是什么?
|
2天前
|
安全 Java API
JAVA并发编程JUC包之CAS原理
在JDK 1.5之后,Java API引入了`java.util.concurrent`包(简称JUC包),提供了多种并发工具类,如原子类`AtomicXX`、线程池`Executors`、信号量`Semaphore`、阻塞队列等。这些工具类简化了并发编程的复杂度。原子类`Atomic`尤其重要,它提供了线程安全的变量更新方法,支持整型、长整型、布尔型、数组及对象属性的原子修改。结合`volatile`关键字,可以实现多线程环境下共享变量的安全修改。
|
9天前
|
监控 算法 Java
掌握Java的垃圾回收机制:从原理到实践
在Java的世界中,垃圾回收(Garbage Collection,简称GC)是一块神秘的领域,它如同一位默默无闻的清洁工,确保内存中不再使用的对象得到妥善处理。本文将带你走进垃圾回收的大门,探索它的工作原理、常见算法及其在实际应用中的调优策略。无论你是初学者还是有一定经验的开发者,这篇文章都将为你揭开垃圾回收的神秘面纱,让你的Java程序运行得更加高效和稳定。
24 5
|
11天前
|
缓存 Java 编译器
JAVA并发编程synchronized全能王的原理
本文详细介绍了Java并发编程中的三大特性:原子性、可见性和有序性,并探讨了多线程环境下可能出现的安全问题。文章通过示例解释了指令重排、可见性及原子性问题,并介绍了`synchronized`如何全面解决这些问题。最后,通过一个多窗口售票示例展示了`synchronized`的具体应用。
|
7天前
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇
|
22天前
|
前端开发 算法 JavaScript
React原理之Diff算法
【8月更文挑战第24天】
|
1天前
|
Java
JAVA并发编程ReentrantLock核心原理剖析
本文介绍了Java并发编程中ReentrantLock的重要性和优势,详细解析了其原理及源码实现。ReentrantLock作为一种可重入锁,弥补了synchronized的不足,如支持公平锁与非公平锁、响应中断等。文章通过源码分析,展示了ReentrantLock如何基于AQS实现公平锁和非公平锁,并解释了两者的具体实现过程。
|
11天前
|
机器学习/深度学习 算法 Python
群智能算法:深入解读人工水母算法:原理、实现与应用
近年来,受自然界生物行为启发的优化算法备受关注。人工水母算法(AJSA)模拟水母在海洋中寻找食物的行为,是一种新颖的优化技术。本文详细解读其原理及实现步骤,并提供代码示例,帮助读者理解这一算法。在多模态、非线性优化问题中,AJSA表现出色,具有广泛应用前景。
|
13天前
|
监控 前端开发 Java
Java里的过滤器和拦截器是什么原理,如何选择?
Java里的过滤器和拦截器是什么原理,如何选择?
11 0