一、优先队列

简介

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

完全二叉树

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

特性

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

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

  • Parent(i) =i / 2,i 的父节点下标
  • Left(i) = 2 * i ,i 的左子节点下标
  • Right(i) = 2 * i +1,i 的右子节点下标
堆的二叉树表现形式
堆的数组表现形式

应用场景

  • 合并有序小文件
  • 高性能定时器
  • 堆排序
  • 查找第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 = items[i];items[i] = items[j];items[j] = tmp;}

堆化算法

  • 上浮算法:将一个数不断的与他的父节点进行对比交换,直到上浮到它该有的位置
//使用上浮算法,使索引k处的元素能在堆中处于一个正确的位置

  • 下沉算法:将一个数不断的与他的子节点中较大(较小)者进行对比交换,直到下沉到它该有的位置
   //使用下沉算法,使索引k处的元素能在堆中处于一个正确的位置private void sink(int k) {while (2 * k <= N) {int min;//判断右节点是否超出限制,超出则与左节点比较if (2 * k + 1 <= N) {//比较左右子节点哪个更大(小),与K交换if (less(2 * k, 2 * k + 1)) {min = 2 * k;} else {min = 2 * k + 1;}} else {min = 2 * k;}//比较当前结点和较小值if (less(k,min)){break;}exch(k, min);k = min;}}

排序算法

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

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

三、索引优先队列

为什么需要索引优先队列

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

原理

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

实现

  • 0.定义一个items来保存元素,这样就可以通过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 = pq[i];pq[i] = pq[j];pq[j] = tmp;qp[pq[i]] = i;qp[pq[j]] = j;}

  • 1.定义一个pq保存每个元素在items中的索引,这个数组用来保持堆有序。
   //保存每个元素在items中的索引,需要保持堆有序private int[] pq;

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

  • 2.定义一个qp数组为pq的逆序,pq的值作为索引,pq的索引作为值。这个数组用来保存items中第N个元素在pq中的位置。
  //为pq的逆序,pq的值作为索引,pq的索引作为值private int[] qp;

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

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

  1. alxctools索引超出了数组界限_[译]V8中的数组类型

    译者:蒋海涛 JavaScript 对象可以和任何属性有关联.对象属性的名称可以包含任何字符.有趣的是 JavaScript 引擎可以选择名称为纯数字的属性来进行优化,而这个属性其实就是数组 inde ...

  2. c索引超出了数组界限_关于MATLAB逻辑数组索引的二三事(二)

    刀剑神域 UW 终章演的什么玩意,都给我看乐了,还不如回去再看一遍加速世界. MATLAB 逻辑数组索引还是非常好用的,MATLAB 中,索引数组常用的有两种方法,一种是线性索引(linear ind ...

  3. 索引超出了数组界限_【每天一题】LeetCode 26. 删除排序数组中的重复项

    开源地址 JiauZhang/algorithms​github.com 题目描述 * https://leetcode-cn.com/problems/remove-duplicates-from- ...

  4. sqldataadapter.fill 索引超出了数组界限_小学生学习C++||第十五节 数组

    存储数据的方式 第一种,变量: 存放1个学生的数学成绩可以定义1个变量存放,那么如果想要存放100个学生的数学成绩应该如何存储呢? 第二种,数组: 引入数组概念: 可以用来表达类型相同的元素的集合,集 ...

  5. Lucene.Net 的“System.IndexOutOfRangeException: 索引超出了数组界限”错误

    堆栈信息如下 System.IndexOutOfRangeException: 索引超出了数组界限. 在 Lucene.Net.Search.AnonymousClassIntParser1.Pars ...

  6. 用ThoughtWorks.QRCode生成二维码时出现“索引超出了数组界限”的错误

    用ThoughtWorks.QRCode生成二维码时出现"索引超出了数组界限"的错误 字符串较长的情况下,用ThoughtWorks.QRCode生成二维码时出现"索引超 ...

  7. mysql blob图片类型存储bug解决:索引超出了数组界限错误,MySqlBlob图片类型存储Bug解决:索引超出了数组界限错误_MySQL...

    告别了一周多的网络,终于回归,突见群里,有网友提了以下问题: CYQ.Data框架测试:mysql数据库测试(保存blob类型的数据会出问题) ,针对mysql数据库做测试:发现更新blog字段,总是 ...

  8. Sql Server 2008的客户端连接工具SQL Server Management Studio连接Sql Server 2012出现的索引超出了数组界限的错误

    使用2008版的SQL Server  Management Studio远程连接Sql Server2012会出现如下的错误,'索引超出了数组界限的错误',当刚打开连接工具就会报如下图的错误: 解决 ...

  9. ThoughtWorks.QRCode 生成QR二维码时提示“索引超出了数组界限”的原因和解决方法

    ThoughtWorks.QRCode 生成QR二维码时提示"索引超出了数组界限"的原因和解决方法 参考文章: (1)ThoughtWorks.QRCode 生成QR二维码时提示& ...

最新文章

  1. 【camera】基于YOLO的车辆多维特征识别系统(车色,车品牌,车标,车型)与PYQT实现(课程设计)
  2. android下载后的app自动安装,Android 7.0 下载APK后自动安装
  3. jQuery是否可以获取与元素关联的所有CSS样式?
  4. c# nullable类型有什么用
  5. BUFF 在C++ 中取其中一部分 并且写到固定的目录下
  6. python float转化为int_python – 将矩阵的某些列从float转换为int
  7. HDU 4278 卡特兰,区间DP
  8. WinRAR去除广告弹窗(完整版)
  9. 金桔智能门锁实现人证房三统一原理
  10. excel 置信区间 计算_Excel 计算置信区间:CONFIDENCE函数详解
  11. 【移动网络】5G NR: 压缩设计与帧结构等核心操作特性
  12. ESP32入门基础之ESP32作为 WIFI Station去连接wifi热点
  13. 做提高打字速度的练习后的漫谈
  14. 第14章-Spring AOP通知(Advice)详解
  15. java中setcolor_Java XWPFRun.setColor方法代码示例
  16. 机器人自动化中的通讯手段
  17. Pythonista——一个随时随地写Python代码的神器
  18. zoj3598----球面三角形内角
  19. imshow, image, imagesc
  20. Springboot旅游社交平台9k9sq计算机毕业设计-课程设计-期末作业-毕设程序代做

热门文章

  1. OpenCV视频分析背景提取与前景提取
  2. 分享一下我为什么可以获得ssp
  3. 解析激光雷达中时序融合的研究现状和发展方向
  4. OpenCV中直方图反向投影算法详解与实现
  5. 使用OpenCV进行对象检测
  6. 基于Python进行相机校准
  7. 【OpenCV 4开发详解】方框滤波
  8. Docker快速验证tomcat单机多实例方案
  9. Linux Tomcat安装,Linux配置Tomcat,Linux Tomcat修改内存,Linux tomcat修改端口
  10. java 中格式化数字