【算法】堆

heap,一棵完全二叉树,使用数组实现的,但具备完全二叉树的一些性质。一般总是满足以下性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。(即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入)

堆一般分为以下两种形式:

  • 大根堆:根节点的值最大,每个节点都大于等于其子树中所有节点的值
  • 小根堆:根节点的值最小,每个节点都小于等于其子树中所有节点的值

两者的总体架构相同,不同的只是元素之间的比较规则

堆的入队和出队的时间复杂度都是O(log n)

在PriorityQueue中,最高优先级的元素总是位于队列的前面,即堆的根节点。(默认是数字越小,优先级越高),常用方法:

  • peek()方法:获取队列中优先级最高的元素
  • poll()方法:从队列中删除并返回优先级最高的元素
  • add()方法:向队列中添加元素
  • remove()方法:移除队列中的某个元素(数组中从左到右的第一个)
  • size()方法:返回当前堆中的元素个数
  • clear()方法:清空堆中的元素,重置堆

PriorityQueue底层使用最小堆来实现,能够自动维护堆的性质。

在实现堆的过程中,通常使用数组来存储堆元素,并通过一些算法实现堆的插入、删除等操作。

小根堆

数组递归实现小根堆

import java.util.*;public class MinHeap {private int[] heap;     //用于实现堆的数组private int size;       //当前数组中最后一个元素的索引private int maxSize;    //总数组长度public MinHeap(int maxSize) {this.maxSize = maxSize;this.size = 0;//从索引为1的位置存储堆中的元素heap = new int[this.maxSize + 1];heap[0] = Integer.MIN_VALUE;}// 获取传入元素的父元素private int parent(int pos) {return pos / 2;}// 获取传入元素的左子元素private int leftChild(int pos) {return 2 * pos;}// 获取传入元素的右子元素private int rightChild(int pos) {return (2 * pos) + 1;}//判断是否是叶子结点private boolean isLeaf(int pos) {return pos > (size / 2) && pos <= size;}//交换位置private void swap(int pos1, int pos2) {int tmp = heap[pos1];heap[pos1] = heap[pos2];heap[pos2] = tmp;}//小根堆化,对传入的元素作为父节点的子树进行重构,用于在插入或删除元素后重新调整堆以保持小根堆的性质private void minHeapify(int pos) {if (!isLeaf(pos)) {//不是叶子结点//如果父元素比左子元素或右子元素大if (heap[pos] > heap[leftChild(pos)] || heap[pos] > heap[rightChild(pos)]) {//交换父元素和两子节点中较小的那个元素,然后重构对应的子树if (heap[leftChild(pos)] < heap[rightChild(pos)]) {swap(pos, leftChild(pos));minHeapify(leftChild(pos));} else {swap(pos, rightChild(pos));minHeapify(rightChild(pos));}}}}//向堆中插入元素public void insert(int element) {if (size >= maxSize) {return;}heap[++size] = element;int current = size;//插入的元素比对应的父元素小,交换位置,不断向上重构while (heap[current] < heap[parent(current)]) {swap(current, parent(current));current = parent(current);}}//获取最小的元素,将最后一个元素放入到原最小元素的位置,然后重构public int extractMin() {int popped = heap[1];heap[1] = heap[size--];minHeapify(1);return popped;}//不断根据父元素打印子节点的元素public void print() {for (int i = 1; i <= size / 2; i++) {System.out.print(" Parent: " + heap[i] + " Left child: " + heap[2 * i] + " Right child: " + heap[2 * i + 1]);System.out.println();}}public static void main(String[] args) {MinHeap minHeap = new MinHeap(10);minHeap.insert(5);minHeap.insert(3);minHeap.insert(17);minHeap.print();System.out.println("The Min val is " + minHeap.extractMin());}
}

数组非递归实现小根堆

import java.util.Arrays;public class MinHeap {private int[] heap;private int size;public MinHeap(int capacity) {heap = new int[capacity];size = 0;}public void insert(int val) {if (size == heap.length) {//如果空间不够则将数组的长度扩充一倍heap = Arrays.copyOf(heap, size * 2);}heap[size++] = val;int i = size - 1;while (i > 0 && heap[i] < heap[(i - 1) / 2]) {int temp = heap[i];heap[i] = heap[(i - 1) / 2];heap[(i - 1) / 2] = temp;i = (i - 1) / 2;}}public int pop() {if (size == 0) {throw new IllegalStateException("Heap is empty");}int root = heap[0];heap[0] = heap[--size];int i = 0;while (i * 2 + 1 < size) {int child = i * 2 + 1;//如果右节点存在而且比左节点小,则指向右节点,否则指向左节点if (child + 1 < size && heap[child + 1] < heap[child]) {child++;}if (heap[child] < heap[i]) {int temp = heap[i];heap[i] = heap[child];heap[child] = temp;i = child;} else {break;}}return root;}public boolean isEmpty() {return size == 0;}
}

在 insert() 方法中,先将元素插入数组末尾,然后将其上移至合适位置,直到父节点小于等于该元素或者该元素上移到根节点为止。在 pop() 方法中,将根节点弹出后,将数组末尾元素放置根节点处,然后将其下移至合适位置,直到子节点大于等于该元素或者该元素下移到叶子节点为止。

非递归实现,因此空间复杂度较递归实现会小一些,但是代码实现会更加复杂。

非递归实现中需要学习的还有:

抛出异常

if (size == 0) {throw new IllegalStateException("Heap is empty");
}

扩充堆大小

heap = Arrays.copyOf(heap, size * 2);

PriorityQueue实现小根堆

	public static void main(String[] args) {//可以直接使用PriorityQueue实现小根堆,因为PriorityQueue内部默认就是使用小根堆实现的//PriorityQueue<Integer> minHeap = new PriorityQueue<>();//传入了一个Comparator对象,重写了compare方法,使得PriorityQueue中的元素按照从小到大的顺序排列。PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {public int compare(Integer a, Integer b) {return a - b;}});minHeap.add(10);minHeap.add(20);minHeap.add(15);System.out.println("Smallest element: " + minHeap.peek());System.out.println("Removed element: " + minHeap.poll());System.out.println("New smallest element: " + minHeap.peek());}

小根堆的实现可以使用Java中的PriorityQueue类,只需要在创建PriorityQueue对象时传入一个Comparator对象,实现Comparator的compare方法来定义小根堆的比较方式。

大根堆

数组递归实现大根堆

import java.util.*;public class MaxHeap {private int[] heap;     //用于实现堆的数组private int size;       //当前数组中最后一个元素的索引private int maxSize;    //总数组长度public MaxHeap(int maxSize) {this.maxSize = maxSize;this.size = 0;//从索引为1的位置存储堆中的元素heap = new int[this.maxSize + 1];heap[0] = Integer.MAX_VALUE;}// 获取传入元素的父元素private int parent(int pos) {return pos / 2;}// 获取传入元素的左子元素private int leftChild(int pos) {return 2 * pos;}// 获取传入元素的右子元素private int rightChild(int pos) {return (2 * pos) + 1;}//判断是否是叶子结点private boolean isLeaf(int pos) {return pos > (size / 2) && pos <= size;}//交换位置private void swap(int pos1, int pos2) {int tmp = heap[pos1];heap[pos1] = heap[pos2];heap[pos2] = tmp;}//小根堆化,对传入的元素作为父节点的子树进行重构private void maxHeapify(int pos) {if (!isLeaf(pos)) {//不是叶子结点//如果父元素比左子元素或右子元素小if (heap[pos] < heap[leftChild(pos)] || heap[pos] < heap[rightChild(pos)]) {//交换父元素和两子节点中较小的那个元素,然后重构对应的子树if (heap[leftChild(pos)] > heap[rightChild(pos)]) {swap(pos, leftChild(pos));maxHeapify(leftChild(pos));} else {swap(pos, rightChild(pos));maxHeapify(rightChild(pos));}}}}//向堆中插入元素public void insert(int element) {if (size >= maxSize) {return;}heap[++size] = element;int current = size;//插入的元素比对应的父元素小,交换位置,不断向上重构while (heap[current] > heap[parent(current)]) {swap(current, parent(current));current = parent(current);}}//获取最小的元素,将最后一个元素放入到原最小元素的位置,然后重构public int extractMax() {int popped = heap[1];heap[1] = heap[size--];maxHeapify(1);return popped;}//不断根据父元素打印子节点的元素public void print() {for (int i = 1; i <= size / 2; i++) {System.out.print(" Parent: " + heap[i] + " Left child: " + heap[2 * i] + " Right child: " + heap[2 * i + 1]);System.out.println();}}public static void main(String[] args) {MaxHeap maxHeap = new MaxHeap(10);maxHeap.insert(5);maxHeap.insert(3);maxHeap.insert(17);maxHeap.print();System.out.println("The Max val is " + maxHeap.extractMax());}
}

PriorityQueue实现大根堆

	public static void main(String[] args) {// 传入了一个Comparator对象,重写了compare方法,使得PriorityQueue中的元素按照从大到小的顺序排列。PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {public int compare(Integer a, Integer b) {return b - a;}});maxHeap.add(10);maxHeap.add(20);maxHeap.add(15);System.out.println("Max element: " + maxHeap.peek());System.out.println("Removed element: " + maxHeap.poll());System.out.println("New Max element: " + maxHeap.peek());}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/70563.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++高性能Web开发框架全解析:2025技术选型指南

一、工业级框架深度解析&#xff08;附性能实测&#xff09; 1. Drogon v2.1&#xff1a;异步框架性能王者 核心架构&#xff1a; Reactor 非阻塞I/O线程池&#xff08;参考Nginx模型&#xff09; 协程实现&#xff1a;基于Boost.Coroutine2&#xff08;兼容C11&#xff09;…

使用PHP接入纯真IP库:实现IP地址地理位置查询

引言 在日常开发中,我们经常需要根据用户的IP地址获取其地理位置信息,例如国家、省份、城市等。纯真IP库(QQWry)是一个常用的IP地址数据库,提供了丰富的IP地址与地理位置的映射关系。本文将介绍如何使用PHP接入纯真IP库,并通过一个完整的案例演示如何实现IP地址的地理位…

Django ORM 的常用字段类型、外键关联的跨表引用技巧,以及 `_` 和 `__` 的使用场景

一、Django ORM 常用字段类型 1. 基础字段类型 字段类型说明示例CharField字符串字段&#xff0c;必须指定 max_lengthname models.CharField(max_length50)IntegerField整数字段age models.IntegerField()BooleanField布尔值字段is_active models.BooleanField()DateFiel…

java递归求自然数列的前n项和

概述 实现 /*** 数列 1 2 3 ... n ...* 递归求数列的前n项和* param n* return*/private static long calSum(long n){if (n1) return 1;else {return ncalSum(n-1); // 前n项的和 即第n项的值前n-1项的和}}测试用例 public static void main(String[] args) {long res1 cal…

【Golang 面试题】每日 3 题(六十五)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

16、Python面试题解析:python中的浅拷贝和深拷贝

在 Python 中&#xff0c;浅拷贝&#xff08;Shallow Copy&#xff09; 和 深拷贝&#xff08;Deep Copy&#xff09; 是处理对象复制的两种重要机制&#xff0c;它们的区别主要体现在对嵌套对象的处理方式上。以下是详细解析&#xff1a; 1. 浅拷贝&#xff08;Shallow Copy&a…

【Godot4.3】题目与答案解析合并器

免责申明 本文和工具截图中涉及题库和题目&#xff0c;均为本人自学使用&#xff0c;并未有商业和传播企图。如有侵害&#xff0c;联系删改。 概述 笔者本人医学专业从业人员&#xff0c;编程只是业余爱好。在自己的专业应考学习过程当中&#xff1a; 有时候不太喜欢纸质题库…

Lm studio本地部署DeepSeek

为什么用Lm studio Ollama官网下载过慢或失败&#xff08;Lm默认下载源无法下载&#xff0c;但可以更换下载源&#xff09;Ollama默认安装至C盘一部分Nivida显卡无法吃满显存资源一部分AMD显卡替换rocm文件后无法启动 Lm studio安装 官网下载&#xff1a;LM Studio - Discov…

基于Qlearning强化学习的2DoF机械臂运动控制系统matlab仿真

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 2DoF机械臂运动学模型 2.2 Q-learning强化学习算法原理 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 仿真操作步骤可参…

Unity贴图与模型相关知识

一、贴图 1.贴图的类型与形状 贴图类型 贴图形状 2.在Unity中可使用一张普通贴图来生成对应的法线贴图&#xff08;但并不规范&#xff09; 复制一张该贴图将复制后的贴图类型改为Normal Map 3.贴图的sRGB与Alpha sRGB&#xff1a;勾选此选项代表此贴图存储于Gamma空间中…

快速上手 Unstructured:安装、Docker部署及PDF文档解析示例

1. 核心概念 1.1 Unstructured简介 Unstructured 是一个强大的 Python 库,专注于从非结构化数据中提取和预处理文本信息,广泛应用于 PDF、Word 文档、HTML 等多种格式的文件处理。其核心功能包括分区、清理、暂存和分块,能够将复杂的非结构化文档转换为结构化输出,为后续…

pyecharts介绍

文章目录 介绍安装pyecharts基本使用全局配置选项 折线图相关配置地图模块使用柱状图使用 介绍 echarts虑是个由百度开源的数据可视化&#xff0c;凭借着良好的交互性&#xff0c;精巧的图表设计&#xff0c;得到了众多开发者的认可&#xff0c;而Pyhon是门富有表达力的语言&a…

Fisher信息矩阵与Hessian矩阵:区别与联系全解析

Fisher信息矩阵与Hessian矩阵&#xff1a;区别与联系全解析 在统计学和机器学习中&#xff0c;Fisher信息矩阵&#xff08;FIM&#xff09;和Hessian矩阵是两个经常出现的概念&#xff0c;它们都与“二阶信息”有关&#xff0c;常用来描述函数的曲率或参数的敏感性。你可能听说…

python与C系列语言的差异总结(1)

/ 表示浮点除法 // 表示整数除法 print(8/3)print(8//3)布尔型 False/True 首字母大写 整数的大小是没有限制的&#xff0c;会根据需要自动增长&#xff0c;仅受限于可用内存的大小。 m**n表示m的n次方 x 4.3 ** 2.4print(x)print(3.5e30 * 2.77e45)print(1000000001.0 *…

Python selenium 库

Selenium 是一个用于自动化 Web 浏览器操作的强大工具&#xff0c;广泛应用于 Web 应用程序测试、网页数据抓取和任务自动化等场景。 Selenium 为各种编程语言提供了 API&#xff0c;用作测试。 目前的官方 API 文档有 C#、JavaScript、Java、Python、Ruby。 安装 Selenium 和…

vllm部署LLM(qwen2.5,llama,deepseek)

目录 环境 qwen2.5-1.5b-instruct 模型下载 vllm 安装 验证安装 vllm 启动 查看当前模型列表 OpenAI Completions API&#xff08;文本生成&#xff09; OpenAI Chat Completions API&#xff08;chat 对话&#xff09; vllm 进程查看&#xff0c;kill llama3 deep…

Python NumPy库使用指南:从入门到精通

1. 引言 NumPy(Numerical Python)是 Python 中用于科学计算的核心库之一。它提供了强大的多维数组对象(ndarray),以及一系列高效的数学函数,能够轻松处理大规模的数值数据。NumPy 是许多其他科学计算库(如 Pandas、Matplotlib、Scikit-learn 等)的基础。 本文将详细介…

15.2 智能销售顾问系统技术架构解密:构建企业级知识驱动型对话引擎

智能销售顾问系统技术架构解密:构建企业级知识驱动型对话引擎 关键词:RAG 架构设计、销售知识库系统、LoRA 微调优化、多模态交互引擎、高并发服务部署 1. 系统技术架构全景解析 1.1 核心架构设计图 #mermaid-svg-UBkTgaR5lf5WfGMa {font-family:"trebuchet ms",…

用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解

DeepSeek R1 的完整训练流程核心在于&#xff0c;在其基础模型 DeepSeek V3 之上&#xff0c;运用了多种强化学习策略。 本文将从一个可本地运行的基础模型起步&#xff0c;并参照其技术报告&#xff0c;完全从零开始构建 DeepSeek R1&#xff0c;理论结合实践&#xff0c;逐步…

爬虫基础入门之爬取豆瓣电影Top250-Re正则的使用

网址:豆瓣电影 Top 250 本案例所需要的模块 requests (用于发送HTTP请求)re (用于字符串匹配和操作) 确定需要爬取的数据 &#xff1a; 电影的名称电影的年份电影的评分电影评论人数 一. 发送请求 模拟浏览器向服务器发送请求 准备工作 -分析页面: F12 or 右击点击检查 查看…