Java索引优先队列设计思路与实现

Java 学习+面试指南:https://javaxiaobear.cn

1、实现思路

  1. 存储数据时,给每一个数据元素关联一个整数,例如insert(int k,T t),我们可以看做k是t关联的整数,那么我们的实现需要通过k这个值,快速获取到队列中t这个元素,此时有个k这个值需要具有唯一性。

    最直观的想法就是我们可以用一个T[] items数组来保存数据元素,在insert(int k,T t)完成插入时,可以把k看做是items数组的索引,把t元素放到items数组的索引k处,这样我们再根据k获取元素t时就很方便了,直接就可以拿到items[k]即可。

  2. 第一步完成后的结果,虽然我们给每个元素关联了一个整数,并且可以使用这个整数快速的获取到该元素,但是,items数组中的元素顺序是随机的,并不是堆有序的,所以,为了完成这个需求,我们可以增加一个数组int[]pq,来保存每个元素在items数组中的索引,pq数组需要堆有序,也就是说,pq[1]对应的数据元素items[pq[1]]要小于等于pq[2]和pq[3]对应的数据元素items[pq[2]]和items[pq[3]]。

  3. 通过第二步的分析,我们可以发现,其实我们通过上浮和下沉做堆调整的时候,其实调整的是pq数组。如果需要对items中的元素进行修改,比如让items[0]=“H”,那么很显然,我们需要对pq中的数据做堆调整,而且是调整pq[9]中元素的位置。但现在就会遇到一个问题,我们修改的是items数组中0索引处的值,如何才能快速的知道需要挑中pq[9]中元素的位置呢?

    最直观的想法就是遍历pq数组,拿出每一个元素和0做比较,如果当前元素是0,那么调整该索引处的元素即可,但是效率很低。
    我们可以另外增加一个数组,int[] qp,用来存储pq的逆序。例如:
    在pq数组中:pq[1]=6;
    那么在qp数组中,把6作为索引,1作为值,结果是:qp[6]=1;

当有了pq数组后,如果我们修改items[0]=“H”,那么就可以先通过索引0,在qp数组中找到qp的索引:qp[0]=9,那么直接调整pq[9]即可。

2、API设计

类名IndexMinPriorityQueue
构造方法IndexMinPriorityQueue(int capacity):创建容量为capacity的IndexMinPriorityQueue对象
成员方法private boolean less(int i,int j):判断堆中索引i处的元素是否小于索引j处的元素
private void exch(int i,int j):交换堆中i索引和j索引处的值
public int delMin():删除队列中最小的元素,并返回该元素关联的索引
public void insert(int i,T t):往队列中插入一个元素,并关联索引i
private void swim(int k):使用上浮算法,使索引k处的元素能在堆中处于一个正确的位置
private void sink(int k):使用下沉算法,使索引k处的元素能在堆中处于一个正确的位置
public int size():获取队列中元素的个数
public boolean isEmpty():判断队列是否为空
public boolean contains(int k):判断k对应的元素是否存在
public void changeItem(int i, T t):把与索引i关联的元素修改为为t
public int minIndex():最小元素关联的索引
public void delete(int i):删除索引i关联的元素
成员变量private T[] imtes : 用来存储元素的数组
private int[] pq:保存每个元素在items数组中的索引,pq数组需要堆有序
private int [] qp:保存qp的逆序,pq的值作为索引,pq的索引作为值
private int N:记录堆中元素的个数

3、代码实现

public class IndexMinPriorityQueue<T extends Comparable<T>> {/*** 堆中元素*/private T[] items;/*** 元素个数*/private int size;/*** 保存每个元素在items数组中的索引,pq数组需要堆有序*/private int[] pq;/*** 保存qp的逆序,pq的值作为索引,pq的索引作为值*/private int[] qp;public IndexMinPriorityQueue(int capacity){items = (T[]) new Comparable[capacity+1];size = 0;qp = new int[capacity+1];pq = new int[capacity+1];Arrays.fill(qp, -1);}/*** 判断堆中索引i处的元素是否小于索引j处的元素* @param i* @param j* @return*/private boolean less(int i,int j){return items[pq[i]].compareTo(items[pq[j]]) < 0;}/*** 换堆中i索引和j索引处的值* @param i* @param j*/private void swap(int i,int j){//先交换pq数组中的值int temp = pq[i];pq[i] = pq[j];pq[j] = temp;//更新qp数组中的值qp[pq[i]] = i;qp[pq[j]] = j;}/*** 删除队列中最小的元素,并返回该元素关联的索引* @return*/public int delMin(){//找到items中最小元素的索引int minIndex = pq[1];//交换pq中索引1处的值和N处的值swap(1, size);//删除qp中索引pq[N]处的值qp[pq[size]] = -1;//删除pq中索引N处的值pq[size] = -1;//删除items中的最小元素items[minIndex] = null;//元素数量-1size--;//对pq[1]做下沉,让堆有序sink(1);return minIndex;}/*** 往队列中插入一个元素,并关联索引i* @param i* @param t*/public void insert(int i,T t){if(contains(i)){throw new RuntimeException("该索引已存在!");}size++;//把元素存放到items数组中items[i] = t;//使用pq存放i这个索引pq[size] = i;//在qp的i索引处存放Nqp[i] = size;//上浮items[pq[N]],让pq堆有序swim(size);}/*** 使用上浮算法,使索引k处的元素能在堆中处于一个正确的位置* @param k*/private void swim(int k){while (1 < k){//比较当前结点和父结点,如果当前结点比父结点小,则交换位置if(less(k,k/2)){swap(k,k/2);}k = k/2;}}/*** :使用下沉算法,使索引k处的元素能在堆中处于一个正确的位置* @param k*/private void sink(int k){//如果当前结点已经没有子结点了,则结束下沉while (2*k <= size){int min = 2*k;if(2*k+1 <= size && less(2*k+1,2*k)){min = 2*k + 1;}if(less(k,min)){break;}swap(k,min);k = min;}}/*** :获取队列中元素的个数* @return*/public int size(){return size;}/*** :判断队列是否为空* @return*/public boolean isEmpty(){return size == 0;}/*** :判断k对应的元素是否存在* @param k* @return*/public boolean contains(int k){//默认情况下,qp的所有元素都为-1,如果某个位置插入了数据,则不为-1return qp[k] != -1;}/*** :把与索引i关联的元素修改为为t* @param i* @param t*/public void changeItem(int i, T t){//修改item数组中索引i的值为titems[i] = t;//找到i在pq中的位置int i1 = pq[i];//对pq[i1]做下沉,让堆有序sink(i1);//对pq[k]做上浮,让堆有序swim(i1);}/*** :最小元素关联的索引* @return*/public int minIndex(){//pq的索引1处,存放的是最小元素在items中的索引return pq[1];}/*** :删除索引i关联的元素* @param i*/public void delete(int i){//找出i在pq中的索引int k = pq[i];//把pq中索引k处的值和索引N处的值交换swap(k,size);//删除qp中索引pq[N]处的值qp[pq[size]] = -1;//删除pq中索引N处的值pq[size] = -1;//删除items中索引i处的值items[i] = null;//元素数量-1size--;//对pq[k]做下沉,让堆有序sink(k);//对pq[k]做上浮,让堆有序swim(k);}
}
  • 测试类

    public class IndexMinPriorityQueueTest {public static void main(String[] args) {String[] arr = {"S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"};IndexMinPriorityQueue<String> indexMinPQ = new IndexMinPriorityQueue<>(20);//插入for (int i = 0; i < arr.length; i++) {indexMinPQ.insert(i,arr[i]);}System.out.println(indexMinPQ.size());//获取最小值的索引System.out.println(indexMinPQ.minIndex());//测试修改indexMinPQ.changeItem(0,"Z");int minIndex=-1;while(!indexMinPQ.isEmpty()){minIndex = indexMinPQ.delMin();System.out.print(minIndex+",");}}
    }
    

    输出

    11
    6
    10,4,9,7,1,8,2,3,5,0,0,
    

在这里插入图片描述

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

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

相关文章

使用使用maven后jstl标签库无法使用

创建maven项目后配置了jstl标签库的依赖&#xff0c;但是一直不行&#xff0c;jsp页面还是原样给我输出&#xff0c;然后去网上找了许多办法&#xff0c;类似于配置文件之类的&#xff0c;结果发现对我并没有什么用&#xff0c;还是原样输出 然后就各种查找&#xff0c;发现了一…

大数据本地环境搭建-Linux基础环境搭建

1.安装VMware 下载 VMware Workstation Pro | CN 2.配置虚拟网卡 3.Windows网络配置 4.安装centos7.9 Download (centos.org) 4.1 新建虚拟机 如果开机的时候电脑蓝屏使用WindowsR输入optionalfeatures 打开启用或关闭Windows功能->勾选打开以下两项 重启 继续安装ce…

C++力扣题目-- 二叉树层序遍历

102.二叉树的层序遍历(opens new window)107.二叉树的层次遍历II(opens new window)199.二叉树的右视图(opens new window)637.二叉树的层平均值(opens new window)429.N叉树的层序遍历(opens new window)515.在每个树行中找最大值(opens new window)116.填充每个节点的下一个右…

WPS或word中英文字母自动调整大小写,取消自动首字母大写,全部英文单词首字母大小写变换方法

提示&#xff1a;写英文论文时&#xff0c;如何实现英文字母大小写的自动切换&#xff0c;不用再傻傻的一个字母一个字母的编辑了&#xff0c;一篇文章搞定WPS与Word中字母大小写切换 文章目录 一、WPS英文单词大小写自动修改与首字母大写调整英文字母全部由大写变成小写 或 小…

怎样的摆渡系统,能实现安全可管控的跨网数据传输?

大数据时代&#xff0c;数据在流通与传输的过程中&#xff0c;更需要注意到数据的安全防护&#xff0c;护航数据价值。“让数据主宰一切的隐忧”&#xff0c;数字战争的时代&#xff0c;各国早已认识到网络安全愈发重要&#xff0c;数据也成为各国发展的重要武器。 出于安全性和…

爬虫瑞数5.5案例:某证券

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 一、瑞数简介 瑞数动态安全 Botgate&#xff08;机器人防火墙&#xff09;以“动态安全”技术为核心&#xff0c;通过动态封装…

SwiftUI之深入解析Alignment Guides的超实用实战教程

一、Alignment Guide 简介 Alignment guides 是一个强大的布局工具&#xff0c;但通常未被充分利用。在很多情况下&#xff0c;它们可以帮助我们避免更复杂的选项&#xff0c;比如锚点偏好。如下所示&#xff0c;对对齐的更改也可以自动&#xff08;并且容易地&#xff09;动画…

Spring Cloud 介绍

文章目录 微服务技术栈Spring Cloud 介绍京东、阿里的微服务架构SpringBoot 和 SpringCloud 版本选择Springboot版本选择Springcloud版本选择Springcloud和Springboot之间的依赖关系如何看Spring Cloud 组件的升级替换 微服务技术栈 [toc] Spring Cloud 介绍 Spring Cloud是…

ULINK2仿真器安装使用之工程设置

一、 ULINK2仿真器 ULINK2是ARM公司最新推出的配套RealView MDK使用的仿真器&#xff0c;是ULink仿真器的升级版本。ULINK2不仅具有ULINK仿真器的所有功能&#xff0c;还增加了串行调试&#xff08;SWD&#xff09;支持&#xff0c;返回时钟支持和实时代理等功能。开发工程师通…

基于python热门旅游景点推荐系统+爬虫技术

大数据分析&#xff0c;数据可视化等皆可用。 源码分享。

vue-vben-admin 与.net core 结合实例 【自学与教学 小白教程】---第3节

ue-vben-admin 与.net core 结合实例 这里计划使用.net core 作为后端 。目标&#xff1a;打造好看 易用 开箱即用 的netcore一体化框架。Vue Vben Admin For NetCore 取命 hcrain-vvadmin 我不是前端人员 但有时开发还是要写一些界面。 之前使用layui是时候 狠心升级下了。 …

kubesphere和k8s的使用分享

文章目录 什么是kubernetesKubernetes的部分核心概念互式可视化管理平台与kubernetes的关系市面是常见的kubernetes管理平台 什么是kubesphereKubesphere默认安装的组件Kubesphere涉及的服务组件kubesphere的安装Kubesphere相关的内容 什么是kubernetes 就在这场因“容器”而起…

性能优化--实战利用arthas排查java服务cpu占用过高的问题

使用jps -l查看目前的java应用进程 启动arthas&#xff0c;选择需要监控的进程 dashboar查看该应用整体情况 使用thread命令&#xff0c;查看占用cpu过高的几个线程ID 然后使用thread 线程ID查看具体线程在执行哪些内容&#xff0c;可以看到对应的类和方法 正在上传… 重…

OpenWrt智能路由器Wan PPPoE拨号配置方法

OpenWrt智能路由器的wan PPPoE拨号配置方法和我们常见的不太一样, 需要先找到wan网卡,然后将协议切换为 PPPoE然后才能看到输入上网账号和密码的地方. 首先登录路由器 http://openwrt.lan/ 然后找到 Network --> Interfaces 这里会显示你当前的路由器的所有接口, 选择 …

MySQL8.0 升级

将 MySQL8.0.30 升级到 MySQL8.0.32 备份旧数据 rootLAPTOP-FPIQJ438:/data/backup# xtrabackup --backup --userroot --password123456 --socket/tmp/mysql.sock --target-dir/data/backup/ 2024-01-08T16:46:38.98768708:00 0 [Note] [MY-011825] [Xtrabackup] recognized s…

连接服务器Mysql出现“Host ‘xxx‘ is not allowed to connect to this MySQL server“解决方法

远程连接提示&#xff1a;Host xxx is not allowed to connect to this MySQL server。是mysql未开启mysql远程访问权限导致。 登录mysql&#xff0c;发现出现了 Access denied for user ‘root’ T’localhost (using password: YES) 此时先找到my.cnf文件,使用命令mysql --…

http跟https有什么区别?

HTTPS和HTTP的概念&#xff1a; HTTP&#xff1a;是互联网上应用最为广泛的一种网络协议&#xff0c;是一个客户端和服务器端请求和应答的标准&#xff08;TCP&#xff09;&#xff0c;用于从WWW服务器传输超文本到本地浏览器的传输协议&#xff0c;它可以使浏览器更加高效&am…

智慧灌溉解决方案(基于物联网的智能灌溉系统)

​ 详情&#xff1a;智慧水务数字孪生安全监测解决方案提供商-星创 (key-iot.com.cn) 随着农业IOT的快速发展,智慧灌溉正成为提高农业水资源利用效率,实现精准灌溉的重要技术手段。完整的智慧灌溉系统由实地各类传感设备以及后台管理软件平台组成,可以实现对整个灌区的监测和精…

python(17)--文件的输入/输出

前言 在Python中&#xff0c;文件文本操作是非常重要的&#xff0c;主要有以下几个原因&#xff1a; 数据持久性&#xff1a;当你需要长期存储数据&#xff0c;如用户的个人信息、交易记录或数据库元数据等&#xff0c;将数据保存在文件中是一种常见的方法。文件系统提供了持…

步进电机介绍

一、什么是步进电机&#xff1a; 步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机。每输入一个脉冲信号&#xff0c;转子就转动一个角度或前进一步&#xff0c;其输出的角位移或线位移与输入的脉冲数成正比&#xff0c;转速与脉冲频率成正比。因此&#xff0c;步…