0

0

java代码怎样实现堆的向上调整与向下调整 java代码堆操作的实用实现方法​

看不見的法師

看不見的法師

发布时间:2025-08-07 19:23:01

|

369人浏览过

|

来源于php中文网

原创

使用java构建完整堆需定义包含数组、大小和容量的类,并实现插入、删除、获取堆顶等方法;2. 插入时先将元素放入数组末尾并执行向上调整以恢复堆性质;3. 删除堆顶时用最后一个元素替换堆顶并执行向下调整;4. 获取堆顶直接返回数组首元素;5. 向上调整从插入位置比较父节点直至根节点满足堆性质;6. 向下调整从根节点开始比较子节点并交换最大者直至子树满足堆性质;7. 堆排序通过先构建最大堆再依次将堆顶与末尾元素交换并调整堆完成排序;8. 堆排序时间复杂度为o(n log n),空间复杂度为o(1),但不稳定;9. 优先级队列利用堆实现,java中priorityqueue默认为最小堆,可通过comparator实现最大堆;10. 堆广泛应用于任务调度、事件处理、huffman编码及图算法如dijkstra和prim算法中。

java代码怎样实现堆的向上调整与向下调整 java代码堆操作的实用实现方法​

堆的向上调整和向下调整是堆排序和优先级队列等数据结构中非常关键的操作。它们用于维护堆的性质,确保堆顶元素始终满足特定条件(例如,最大堆中堆顶是最大值)。

 // 向上调整(Sift Up):用于在堆尾插入元素后,维护堆的性质
    public static void heapifyUp(int[] arr, int index) {
        while (index > 0) {
            int parentIndex = (index - 1) / 2;
            if (arr[index] > arr[parentIndex]) { // 最大堆,如果子节点大于父节点,则交换
                swap(arr, index, parentIndex);
                index = parentIndex;
            } else {
                break; // 满足堆性质,停止调整
            }
        }
    }

    // 向下调整(Sift Down):用于在堆顶删除元素后,维护堆的性质
    public static void heapifyDown(int[] arr, int index, int heapSize) {
        while (true) {
            int leftChildIndex = 2 * index + 1;
            int rightChildIndex = 2 * index + 2;
            int largest = index;

            if (leftChildIndex < heapSize && arr[leftChildIndex] > arr[largest]) {
                largest = leftChildIndex;
            }

            if (rightChildIndex < heapSize && arr[rightChildIndex] > arr[largest]) {
                largest = rightChildIndex;
            }

            if (largest != index) {
                swap(arr, index, largest);
                index = largest;
            } else {
                break; // 满足堆性质,停止调整
            }
        }
    }

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

    public static void main(String[] args) {
        int[] arr = {4, 10, 3, 5, 1};
        // 模拟插入元素后的向上调整
        arr[arr.length - 1] = 12; // 假设在堆尾插入12
        heapifyUp(arr, arr.length - 1);
        System.out.println("向上调整后的堆: " + Arrays.toString(arr));

        // 模拟删除堆顶元素后的向下调整
        arr[0] = arr[arr.length - 1];
        int[] newArr = Arrays.copyOf(arr, arr.length - 1); // 移除最后一个元素
        heapifyDown(newArr, 0, newArr.length);
        System.out.println("向下调整后的堆: " + Arrays.toString(newArr));
    }

如何使用Java代码构建一个完整的堆数据结构?

除了向上和向下调整,一个完整的堆数据结构还需要包括插入、删除、获取堆顶元素等操作。同时,需要一个内部数组来存储堆元素,并维护堆的大小。

import java.util.Arrays;

public class Heap {
    private int[] heapArray;
    private int heapSize;
    private int capacity;

    public Heap(int capacity) {
        this.capacity = capacity;
        this.heapArray = new int[capacity];
        this.heapSize = 0;
    }

    // 插入元素
    public void insert(int key) {
        if (heapSize == capacity) {
            resizeHeap();
        }
        heapArray[heapSize] = key;
        heapifyUp(heapArray, heapSize);
        heapSize++;
    }

    // 获取堆顶元素
    public int peek() {
        if (isEmpty()) {
            throw new IllegalStateException("Heap is empty");
        }
        return heapArray[0];
    }

    // 删除堆顶元素
    public int poll() {
        if (isEmpty()) {
            throw new IllegalStateException("Heap is empty");
        }
        int root = heapArray[0];
        heapArray[0] = heapArray[heapSize - 1];
        heapSize--;
        heapifyDown(heapArray, 0, heapSize);
        return root;
    }

    // 向上调整
    private void heapifyUp(int[] arr, int index) {
        while (index > 0) {
            int parentIndex = (index - 1) / 2;
            if (arr[index] > arr[parentIndex]) {
                swap(arr, index, parentIndex);
                index = parentIndex;
            } else {
                break;
            }
        }
    }

    // 向下调整
    private void heapifyDown(int[] arr, int index, int heapSize) {
        while (true) {
            int leftChildIndex = 2 * index + 1;
            int rightChildIndex = 2 * index + 2;
            int largest = index;

            if (leftChildIndex < heapSize && arr[leftChildIndex] > arr[largest]) {
                largest = leftChildIndex;
            }

            if (rightChildIndex < heapSize && arr[rightChildIndex] > arr[largest]) {
                largest = rightChildIndex;
            }

            if (largest != index) {
                swap(arr, index, largest);
                index = largest;
            } else {
                break;
            }
        }
    }

    // 交换元素
    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // 扩容
    private void resizeHeap() {
        capacity *= 2;
        heapArray = Arrays.copyOf(heapArray, capacity);
    }

    public boolean isEmpty() {
        return heapSize == 0;
    }

    public int size() {
        return heapSize;
    }

    public static void main(String[] args) {
        Heap maxHeap = new Heap(5);
        maxHeap.insert(4);
        maxHeap.insert(10);
        maxHeap.insert(3);
        maxHeap.insert(5);
        maxHeap.insert(1);

        System.out.println("堆顶元素: " + maxHeap.peek());
        System.out.println("删除堆顶元素: " + maxHeap.poll());
        System.out.println("堆顶元素: " + maxHeap.peek());
    }
}

堆排序算法的Java实现及其性能分析

堆排序是一种基于堆数据结构的排序算法。它的基本思想是首先将待排序的数组构建成一个堆,然后将堆顶元素(最大值或最小值)与堆尾元素交换,缩小堆的范围,并重新调整堆,重复这个过程直到所有元素都排序完成。

立即学习Java免费学习笔记(深入)”;

import java.util.Arrays;

public class HeapSort {

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

        // 构建最大堆
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapifyDown(arr, i, n);
        }

        // 排序
        for (int i = n - 1; i > 0; i--) {
            swap(arr, 0, i);
            heapifyDown(arr, 0, i);
        }
    }

    private static void heapifyDown(int[] arr, int index, int heapSize) {
        while (true) {
            int leftChildIndex = 2 * index + 1;
            int rightChildIndex = 2 * index + 2;
            int largest = index;

            if (leftChildIndex < heapSize && arr[leftChildIndex] > arr[largest]) {
                largest = leftChildIndex;
            }

            if (rightChildIndex < heapSize && arr[rightChildIndex] > arr[largest]) {
                largest = rightChildIndex;
            }

            if (largest != index) {
                swap(arr, index, largest);
                index = largest;
            } else {
                break;
            }
        }
    }

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

    public static void main(String[] args) {
        int[] arr = {4, 10, 3, 5, 1, 2};
        heapSort(arr);
        System.out.println("排序后的数组: " + Arrays.toString(arr));
    }
}

性能分析:

Joker AIx
Joker AIx

一站式AI创意生产平台,覆盖图像、视频、音频、文案全品类创作

下载
  • 时间复杂度: 堆排序的时间复杂度为O(n log n),其中n是数组的长度。构建堆的时间复杂度为O(n),排序过程的时间复杂度为O(n log n)。
  • 空间复杂度: 堆排序是一种原地排序算法,只需要常数级别的额外空间,因此空间复杂度为O(1)。
  • 稳定性: 堆排序是不稳定的排序算法。

堆排序的优点是其时间复杂度稳定,且空间复杂度低。但由于其不稳定性,在对稳定性有要求的场景下,可能需要考虑其他排序算法。

堆在优先级队列中的应用场景和Java实现

优先级队列是一种特殊的队列,其中每个元素都关联一个优先级。优先级高的元素先出队。堆非常适合实现优先级队列,因为堆可以快速找到最大或最小元素(取决于最大堆还是最小堆)。

import java.util.PriorityQueue;

public class PriorityQueueExample {

    public static void main(String[] args) {
        // 使用PriorityQueue实现最小优先级队列
        PriorityQueue<Integer> minPriorityQueue = new PriorityQueue<>();

        minPriorityQueue.add(4);
        minPriorityQueue.add(10);
        minPriorityQueue.add(3);
        minPriorityQueue.add(5);
        minPriorityQueue.add(1);

        System.out.println("最小优先级队列: " + minPriorityQueue);
        System.out.println("优先级最高的元素: " + minPriorityQueue.peek());
        System.out.println("删除优先级最高的元素: " + minPriorityQueue.poll());
        System.out.println("优先级最高的元素: " + minPriorityQueue.peek());

        // 使用PriorityQueue实现最大优先级队列 (需要自定义Comparator)
        PriorityQueue<Integer> maxPriorityQueue = new PriorityQueue<>((a, b) -> b - a);

        maxPriorityQueue.add(4);
        maxPriorityQueue.add(10);
        maxPriorityQueue.add(3);
        maxPriorityQueue.add(5);
        maxPriorityQueue.add(1);

        System.out.println("最大优先级队列: " + maxPriorityQueue);
        System.out.println("优先级最高的元素: " + maxPriorityQueue.peek());
        System.out.println("删除优先级最高的元素: " + maxPriorityQueue.poll());
        System.out.println("优先级最高的元素: " + maxPriorityQueue.peek());
    }
}

应用场景:

  • 任务调度: 优先级队列可以用于任务调度,优先级高的任务先执行。
  • 事件处理: 在事件驱动的系统中,优先级队列可以用于处理事件,优先级高的事件先处理。
  • 数据压缩: Huffman编码是一种常用的数据压缩算法,它使用优先级队列来构建Huffman树。
  • 图算法: Dijkstra算法和Prim算法等图算法使用优先级队列来寻找最短路径或最小生成树。

Java的

PriorityQueue
类底层使用堆实现,提供了高效的优先级队列操作。 可以通过自定义
Comparator
来实现最大优先级队列。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

549

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

44

2026.01.06

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

497

2023.08.14

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号