热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

索引超出了数组界限_还在用优先队列?来试试索引优先队列吧(优先队列amp;索引优先队列)...

一、优先队列简介优先队列也被称为堆(heap),队列中允许的操作是先进先出(FIFO),在队尾插

1113e6b6d77a60268a24d783c410b160.png

一、优先队列

简介

优先队列也被称为堆(heap),队列中允许的操作是 先进先出(FIFO),在队尾插入元素,在队头取出元素。而堆也是一样,在堆底插入元素,在堆顶取出元素。二叉树的衍生,有最小堆最大堆的两个概念,将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。通常可以被看做是一棵完全二叉树的数组对象。

完全二叉树

若设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k 层所有的结点都连续集中在最左边,这就是完全二叉树。

d17a51e8857f121d32c9ec2ff5fa46b3.png

特性

1.它是完全二叉树,除了树的最后一层结点不需要是满的,其它的每一层从左到右都是满的,如果最后一层结点不是满的,那么要求左满右不满。

2.它通常用数组来实现。

  • Parent(i) =i / 2,i 的父节点下标
  • Left(i) = 2 * i ,i 的左子节点下标
  • Right(i) = 2 * i +1,i 的右子节点下标

7aa0ee0265472708c397552196fb7f79.png
堆的二叉树表现形式

084f568a4e07e16d7dc7f39a8856f7d4.png
堆的数组表现形式

应用场景

  • 合并有序小文件
  • 高性能定时器
  • 堆排序
  • 查找第K大(小)元素
  • 在朋友和面试官面前装逼

二、优先队列原理

准备好交换元素和比较大小的API,为了代码美观。

//存储堆中的元素private T[] items;//记录堆中元素的个数private int N; //判断堆中索引i处的元素是否小于索引j处的元素private boolean less(int i, int j) {return items[i].compareTo(items[j]) <0;}//交换堆中i索引和j索引处的值private void exch(int i, int j) {T tmp &#61; items[i];items[i] &#61; items[j];items[j] &#61; tmp;}

堆化算法

  • 上浮算法&#xff1a;将一个数不断的与他的父节点进行对比交换&#xff0c;直到上浮到它该有的位置

//使用上浮算法&#xff0c;使索引k处的元素能在堆中处于一个正确的位置

  • 下沉算法&#xff1a;将一个数不断的与他的子节点中较大&#xff08;较小&#xff09;者进行对比交换&#xff0c;直到下沉到它该有的位置

//使用下沉算法&#xff0c;使索引k处的元素能在堆中处于一个正确的位置private void sink(int k) {while (2 * k <&#61; N) {int min;//判断右节点是否超出限制&#xff0c;超出则与左节点比较if (2 * k &#43; 1 <&#61; N) {//比较左右子节点哪个更大&#xff08;小&#xff09;&#xff0c;与K交换if (less(2 * k, 2 * k &#43; 1)) {min &#61; 2 * k;} else {min &#61; 2 * k &#43; 1;}} else {min &#61; 2 * k;}//比较当前结点和较小值if (less(k,min)){break;}exch(k, min);k &#61; min;}}

排序算法

每次堆化后将头节点与最后一个数进行交换&#xff0c;下次与最后一个数减1交换&#xff0c;以此类推&#xff0c;直到有序。

//将最大&#xff08;最小&#xff09;元素与最后的元素交换&#xff0c;完成排序void heapSort(int[] arr) {for (int i &#61; arr.length; i > 0; i--) {buildHeap(arr, i);swap(arr, 0, i - 1);}}//将最后一个父节点依次往前面堆化&#xff0c;以此建立堆void buildHeap(int[] arr, int size) {int parent &#61; ((size - 1) - 1) / 2;for (int i &#61; parent; i >&#61; 0; i--) {heaping(arr, size, i);}}//将一个节点调整&#xff0c;使它在堆中处于正确位置void heaping(int[] arr, int size, int index) {if (index > size) return;int L &#61; 2 * index &#43; 1, R &#61; 2 * index &#43; 2;int max &#61; index;//判断左右节点和父节点哪个大&#xff0c;if (L

三、索引优先队列

为什么需要索引优先队列

解决优先队列没有办法通过索引访问已存在于优先队列中的对象的缺陷。

原理

以时间换空间&#xff0c;利用两个辅助数组来维护优先队列。

实现

  • 0.定义一个items来保存元素&#xff0c;这样就可以通过update(int index,T t)方法来修改元素

//存储堆中的元素private T[] items;//记录堆中元素的个数private int N;//判断堆中索引i处的元素是否小于索引j处的元素private boolean less(int i, int j) {return items[pq[i]].compareTo(items[pq[j]]) <0;}//交换堆中i索引和j索引处的值private void exch(int i, int j) {int tmp &#61; pq[i];pq[i] &#61; pq[j];pq[j] &#61; tmp;qp[pq[i]] &#61; i;qp[pq[j]] &#61; j;}

  • 1.定义一个pq保存每个元素在items中的索引&#xff0c;这个数组用来保持堆有序。

//保存每个元素在items中的索引&#xff0c;需要保持堆有序private int[] pq;

但如果仅仅只是定义一个数组的话&#xff0c;我们需要修改第N个元素时候&#xff0c;无法快速得知第N个元素在pq中的位置&#xff0c;就无法在常数级别的时间复杂度内进行修改。

  • 2.定义一个qp数组为pq的逆序&#xff0c;pq的值作为索引&#xff0c;pq的索引作为值。这个数组用来保存items中第N个元素在pq中的位置。

//为pq的逆序&#xff0c;pq的值作为索引&#xff0c;pq的索引作为值private int[] qp;

  • 3.在增删改的时候利用两个数组在O(1)的时间内更新元素。

//删除索引i关联的元素public void delete(int i) {int del &#61; pq[i];//更新qpqp[del] &#61; -1;//更新itemsitems[del] &#61; null;//将i与N在pq中进行位置交换exch(i, N);//把要删除的&#61;-1&#xff0c;表示删除pq[N] &#61; -1;N--;//调整新堆的位置,维持堆有序sink(i);swim(i);}//把与索引i关联的元素修改为为tpublic void changeItem(int i, T t) {//修改items中i的元素items[i] &#61; t;//通过qp找到i在堆中的位置int heapIndex &#61; qp[i];//堆pq中i进行上浮下移调整sink(heapIndex);swim(heapIndex);}//往堆中插入一个元素public void insert(int i, T t) {if (contains(i)) return;N&#43;&#43;;items[i] &#61; t;pq[N] &#61; i;qp[i] &#61; N;//保持pq堆有序swim(N);}//删除堆中最小的元素,并返回这个最小元素public T delMin() {int min &#61; pq[1];T minObj&#61;items[min];//更新qpqp[min] &#61; -1;//更新itemsitems[min] &#61; null;exch(1, N);pq[N] &#61; -1;N--;sink(1);return minObj;}



推荐阅读
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • 面试经验分享:华为面试四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试
    最近有朋友去华为面试,面试经历包括四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试。80%的人都在第一轮电话面试中失败,因为缺乏基础知识。面试问题涉及 ... [详细]
  • 数据结构与算法的重要性及基本概念、存储结构和算法分析
    数据结构与算法在编程领域中的重要性不可忽视,无论从事何种岗位,都需要掌握数据结构和算法。本文介绍了数据结构与算法的基本概念、存储结构和算法分析。其中包括线性结构、树结构、图结构、栈、队列、串、查找、排序等内容。此外,还介绍了图论算法、贪婪算法、分治算法、动态规划、随机化算法和回溯算法等高级数据结构和算法。掌握这些知识对于提高编程能力、解决问题具有重要意义。 ... [详细]
  • 本文介绍了如何通过维持两个堆来获取一个数据流中的中位数。通过使用最大堆和最小堆,分别保存数据流中较小的一半和较大的一半数值,可以保证两个堆的大小差距为1或0。如果数据流中的数量为奇数,则中位数为较大堆的最大值;如果数量为偶数,则中位数为较大堆的最大值和较小堆的最小值的平均值。可以使用优先队列来实现堆的功能。本文还提供了相应的Java代码实现。 ... [详细]
  • C++ STL复习(13)容器适配器
    STL提供了3种容器适配器,分别为stack栈适配器、queue队列适配器以及priority_queue优先权队列适配器。不同场景下,由于不同的序列式 ... [详细]
author-avatar
keyu5182702936453
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有