【堆】堆的实现(Java)

article/2025/11/7 13:45:00

  今天学习堆这种数据结构。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值;
  • 堆总是一棵完全二叉树。

将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。

1.用优先队列实现

一般我们直接用优先队列实现堆:

// 小顶堆,以 Integer 为例
PriorityQueue<Integer> pq = new PriorityQueue<>();
// 大顶堆
PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> o2 - o1);
PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});
2.用数组实现

我们可以通过自己定义数组以及调整方法来实现堆。对于完全二叉树,用数组存储时,数组中下标为 i 的元素,其左孩子是 2i,右孩子是 2i+1,于是可以得到下面的实现:

public class Main {private final static int len = 101;  // 堆的最大容量,下标从 1 开始,因此len 比元素总数多一个private static int n = 0;	// 堆中元素的个数private static int[] heap = new int[len];// 向下调整,时间复杂度 O(logn)public static void downAdjust(int low, int high) {int i = low, j = i * 2;while (j <= high) {if (j + 1 <= high && heap[j + 1] > heap[j]) {j = j + 1;      // 右孩子更大}if (heap[j] > heap[i]) {    // 孩子比父节点大int temp = heap[i];heap[i] = heap[j];heap[j] = temp;i = j;j = i * 2;} else {    // 不需要调整提前结束break;}}}// 建堆,时间复杂度O(n)public static void createHeap() {for (int i = n / 2; i >= 1; i--) {downAdjust(i, n);}}// 删除堆顶元素,时间复杂度O(logn)public static int deleteTop() {int top = heap[1];heap[1] = heap[n--];downAdjust(1, n);return top;}// 向上调整,时间复杂度O(logn)public static void upAdjust(int low, int high) {int i = high, j = i / 2;while (j >= low) {if (heap[j] < heap[i]) {    // 父节点更小,需要调整int temp = heap[i];heap[i] = heap[j];heap[j] = temp;i = j;j = i / 2;} else {break;}}}// 添加元素public static void insert(int x) {heap[++n] = x;upAdjust(1, n);}public static void main(String[] args) {int[] nums = new int[]{4, 3, 7, 8, 2, 1, 9, 6, 5};// 测试 insertn = 0;for (int num : nums) {insert(num);}while (n != 0) {System.out.print(deleteTop() + " ");}System.out.println();// 测试 createHeapn = nums.length;for (int i = 0; i < n; i++) {heap[i + 1] = nums[i];}createHeap();while (n != 0) {System.out.print(deleteTop() + " ");}}
}
3.练习:力扣373. 查找和最小的 K 对数字

给定两个以 升序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。

定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。

请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (uk,vk) 。

示例 1:

输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
输出: [1,2],[1,4],[1,6]
解释: 返回序列中的前 3 对数:[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

示例 2:

输入: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
输出: [1,1],[1,1]
解释: 返回序列中的前 2 对数:[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]

示例 3:

输入: nums1 = [1,2], nums2 = [3], k = 3 
输出: [1,3],[2,3]
解释: 也可能序列中所有的数对都被返回:[1,3],[2,3]

用优先队列实现堆:

class Solution {public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {// 定义一个堆,大小为 kPriorityQueue<int[]> heap = new PriorityQueue<>(k, new Comparator<int[]>(){@Overridepublic int compare(int[] idx1, int[] idx2) {return nums1[idx1[0]] + nums2[idx1[1]] - nums1[idx2[0]] - nums2[idx2[1]];}});List<List<Integer>> result = new ArrayList<>();int m = nums1.length;int n = nums2.length;// 假设上一个被选择的是[mi, nj],由于 m 和 n 是递增的// 那么下一个一定是 [mi+1, nj] 或者 [mi, nj+1]// 所以先把 m 的每个元素和 n0 组合,加进去,下次加入只需要将 n 的下标加 1 即可for (int i = 0; i < Math.min(m, k); i++) {heap.offer(new int[]{i, 0});}while (k-- > 0 && !heap.isEmpty()) {int[] idx = heap.poll();result.add(Arrays.asList(new Integer[]{nums1[idx[0]], nums2[idx[1]]}));if (idx[1] + 1 < n) {heap.offer(new int[]{idx[0], idx[1] + 1});}}return result;}
}

Reference

[1]力扣373. 查找和最小的 K 对数字:https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums/
欢迎关注。
在这里插入图片描述


http://chatgpt.dhexx.cn/article/WU6GHYQ5.shtml

相关文章

Java之堆和堆排序

目录 一.什么是堆 1.基本介绍 2.堆的实现方式 二.最大堆的实现 1.最大堆 2.思路分析 0.基础操作 1.添加上浮操作 2.删除下沉操作 3.将数组堆化操作 2.代码实现 三.堆排序 1.什么是堆排序 2.思路分析 3.代码实现 一.什么是堆 1.基本介绍 堆是一种数据结构&#…

六、Java堆

一、堆的核心概述 1、概述 1、堆针对一个JVM进程来说是唯一的&#xff0c;也就是一个进程只有一个JVM&#xff0c;但是进程包含多个线程&#xff0c;他们是共享同一堆空间的。 2、一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。 3、Java堆区在JVM启动…

Java数据结构-堆

目录 一、简介二、堆的实现&#xff08;1&#xff09;堆的插入&#xff08;2&#xff09;删除根节点&#xff08;3&#xff09;上浮操作① 大根堆的上浮② 小根堆的上浮 &#xff08;4&#xff09;下沉操作① 大根堆的下沉② 小根堆的下沉 &#xff08;5&#xff09;堆的构造&a…

JVM JAVA中的堆

堆的核心概述&#xff1a; 一个进程对应一个JVM的实例&#xff0c;一个JVM实例中只有一个运行时数据区&#xff0c;里面只有一个方法区和堆&#xff0c;一个进程的多个线程共享方法区和堆&#xff0c;那就要考虑线程的安全问题。 每个线程各有一套程序计数器、本地方法栈、虚拟…

Java堆是如何划分的?

写在前面 本文隶属于专栏《100个问题搞定Java虚拟机》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和文献引用请见100个问题搞定Java虚拟机 解答 Java 虚拟机将堆划分为…

数据结构-堆和堆的Java实现

1. 定义 堆&#xff08;英语&#xff1a;heap)是计算机科学中一类特殊的数据结构的统称。 堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质&#xff1a; 1.堆中某个节点的值总是不大于或不小于其父节点的值&#xff1b; 2.堆总是一棵完全二叉树。 常见的堆有二…

Java数据结构之堆(Heap)

文章目录 一、基本概念二、上浮操作(siftUp)三、下沉操作(siftDown)四、数组堆化五、实现大根堆 提示&#xff1a;以下是本篇文章正文内容&#xff0c;Java系列学习将会持续更新 一、基本概念 堆在逻辑上就是一棵完全二叉树。堆在物理上是储存在数组中。满足任意根节点值>…

JVM--堆

45. JVM--堆 1. 堆的核心概述 一个进程对应一个JVM的实例&#xff0c;一个JVM实例中只有一个运行时数据区&#xff0c;里面只有一个方法区和堆&#xff0c;一个进程的多个线程共享方法区和堆&#xff0c;那就要考虑线程的安全问题。 每个线程各有一套程序计数器、本地方法栈、虚…

java中的堆

文章目录 一、堆的分类二、详述Java堆中各个区域1、堆大小2、新生代 ( Young ) 的划分3、工作原理4、GC日志 一、堆的分类 Java 中的堆是 JVM 管理的最大的一块内存空间&#xff0c;主要用于存放Java类的实例对象 其被划分为两个不同的区域&#xff1a;新生代 ( Young )和老年…

Java数据结构--堆

一.堆的定义及本质 要知道在Java中&#xff0c;堆是以优先级队列来表示的。因此学会了堆&#xff0c;我们也就学会优先级队列 1.堆的定义 当一颗二叉树的每个节点都大于等于它的两个子字节时&#xff0c;它被称为堆有序。而堆是一组能够用堆有序的完全二叉树排序的元素&…

Java数据结构之堆

堆的概念 堆逻辑上是一棵完全二叉树堆物理上是保存在数组中满足任意结点的值都大于其子树中结点的值&#xff0c;叫做大堆&#xff0c;或者大根堆&#xff0c;或者最大堆反之&#xff0c;则是小堆&#xff0c;或者小根堆&#xff0c;或者最小堆堆的基本作用是快速找集合中的最…

常用三极管引脚定义

给大家总结了常用封装的三极管的引脚定义 配套的视频讲解 常用三极管引脚定义

常用电子器件 ——三极管

说明&#xff1a;   本文章旨在总结备份、方便以后查询&#xff0c;由于是个人总结&#xff0c;如有不对&#xff0c;欢迎指正&#xff1b;另外&#xff0c;内容大部分来自网络、书籍、和各类手册&#xff0c;如若侵权请告知&#xff0c;马上删帖致歉。   QQ 群 号&#xf…

三极管开关特性

三极管在我们数字电路和模拟电路中都有大量的应用&#xff0c;在我们开发板上也用了多个三极管。在我们板子上的 LED 小灯部分&#xff0c;就有这个三极管的应用了&#xff0c;图 3-5 的 LED 电路中的 Q16就是一个 PNP 型的三极管。 图 3-5 LED 电路 三极管的初步认识 三极管…

常用三极管入门级电路设计(如何选型和搭电路?)

转自&#xff1a; 常用的三极管电路设计-电阻到底是怎么选的&#xff08;修正后&#xff09;-面包板社区 硬件基础知识---如何设计一个三极管放大电路_学无止境的专栏-CSDN博客_uce怎么算 今天的内容超级简单&#xff0c;主要给硬件新手写点东西&#xff0c;关于三极管实用方…

三极管相关知识点

1.两种类型的三极管图示如下&#xff0c;基极&#xff08;Base&#xff09;、集电极&#xff08;Collector&#xff09;和发射极&#xff08;Emitter&#xff09;&#xff0c;等效二极管电路如图所示 2.三极管的几种工作状态&#xff0c; 3.三极管做开关功能时&#xff0c;工…

三极管的一些基本知识

导通条件 NPN型三极管的导通条件是C点电位>B点电位>E点电位&#xff0c;三极管饱和导通的条件是Ub>Ue,Ub>Uc。 PNP型三极管的导通条件是E点电位>B点电位>C点电位&#xff0c;三极管饱和导通的条件是Ue>Ub,Uc>Ub。 NPN型三极管 1、定义&#xff1a; …

三极管的几点应用

关注星标公众号&#xff0c;不错过精彩内容 直接来源 | 巧学模电数电单片机 在复杂多变的模拟电路中&#xff0c;少不了学习三极管&#xff0c;过往的血泪史&#xff0c;不想再提&#xff0c;什么正偏反偏都给我统统滚蛋&#xff01;今天来点实际的。 三极管有三个工作状态&…

【三极管】

文章目录 一、图片&#xff08;NPN - PNP&#xff09;二、导通、截至、饱和条件&#xff08;一&#xff09;NPN&#xff08;二&#xff09;PNP 三、三极管的作用&#xff08;一&#xff09;开关作用 1、同或、异或、或非、与非—真值表 ① 同或&#xff1a;相同为1&#…

三极管常用封装的引脚排列

描述 三极管具有三个引脚&#xff0c;定义分别为基极b、集电极c、发射极e&#xff0c;在设计电路和设计封装时&#xff0c;这三个引脚的顺序必须和封装对应一致&#xff0c;否则电路无法正常工作&#xff0c;三极管常用的封装有&#xff1a;直插TO-92&#xff0c;贴片SOT-23、S…