Java利用跳跃表解决双重队列问题详解
作者:chengqiuming
这篇文章主要为大家详细介绍了Java如何利用跳跃表来解决双重队列的问题。本文通过一个简单的例题进行了讲解,感兴趣的小伙伴可以了解一下
一 问题描述
银行的每个客户都有一个正整数标识 K,到银行请求服务时将收到一个正整数的优先级 P 。银行经理提议打破传统,在某些时候调用优先级最低的客户,而不是优先级最高的客户。系统将收到以下类型的请求:
① 0,系统需要停止服务。
② 1 K P,将客户 K 及优先级 P 添加到等待列表中。
③ 2,为优先级最高的客户提供服务,并将其从等待名单中删除。
④ 3,为优先级最低的客户提供服务,并将其从等待名单中删除。
二 输入
输入的每一行都包含一个请求,只有最后一行包含停止请求(代码0)。假设有请求在列表中包含新客户(代码1),在同一客户的列表中没有其他请求或有相同的优先级,标识符 K 总是小于10^6 ,优先级 P 总是小于10^7 。一个客户可以多次到银行请求服务,但是每次都获得不同的优先级。
三 输出
对代码为 2 或 3 的每个请求都单行输出所服务客户的标识。若请求在等待列表为空时到达,则输出 0。
四 输入和输出样例
1 输入样例
2
1 20 14
1 30 3
2
1 10 99
3
2
2
0
2 输出样例
0
20
30
10
0
五 分析和设计
本问题包括插入、删除优先级最高元素和删除优先级最低元素等3种操作,可以使用跳跃表解决。
六 代码
package com.platform.modules.alg.alglib.poj3481; import java.util.Random; public class Poj3481D { private int INF = 0x7fffffff; private int MAX_LEVEL = 16; public String output = ""; public String cal(String input) { Init(); int op, num, val; String[] line = input.split("\n"); int count = 0; while (true) { String commad[] = line[count++].split(" "); op = Integer.parseInt(commad[0]); if (op == 1) { num = Integer.parseInt(commad[1]); val = Integer.parseInt(commad[2]); Insert(num, val); } else if (op == 0) { return output; } else if (op == 2) Delete(true); else Delete(false); } } class Node { int num, val; Node forward[] = new Node[MAX_LEVEL]; } public Poj3481D() { for (int i = 0; i < updata.length; i++) { updata[i] = new Node(); } } Node head; Node updata[] = new Node[MAX_LEVEL]; int level, max_k, min_k; void Init() { level = 0; max_k = -INF; min_k = INF; head = new Node(); for (int i = 0; i < MAX_LEVEL; i++) head.forward[i] = null; head.val = -INF; } // 按规则选择数据应该在哪层插入 int RandomLevel() { int lay = 0; while (new Random().nextInt(100) % 2 == 0 && lay < MAX_LEVEL - 1) lay++; return lay; } // 查找最接近val的元素 Node Find(int val) { Node p = head; for (int i = level; i >= 0; i--) { while (p.forward[i] != null && p.forward[i].val < val) p = p.forward[i]; updata[i] = p; // 记录搜索过程中各级走过的最大节点位置 } return p; } void Insert(int num, int val) { if (val > max_k) max_k = val; if (val < min_k) min_k = val; Node s; int lay = RandomLevel(); if (lay > level) // 要插入的层 > 现有层数 level = lay; Find(val); //查询 s = new Node(); // 创建一个新节点 s.num = num; s.val = val; for (int i = 0; i < MAX_LEVEL; i++) s.forward[i] = null; for (int i = 0; i <= lay; i++) { // 插入操作 s.forward[i] = updata[i].forward[i]; updata[i].forward[i] = s; } } // flag=false 表示删除最小值,true 表示删除最大值 void Delete(boolean flag) { int d; if (flag) d = max_k; else d = min_k; if (d == -INF || d == INF) { // 说明还没有插入元素 output += "0\n"; return; } Node p = Find(d); if (p.forward[0] != null && p.forward[0].val == d) { output += String.format("%d\n", p.forward[0].num); if (p.val == -INF && p.forward[0].forward[0] == null) // 删除唯一节点 { max_k = -INF; min_k = INF; } else { if (flag) max_k = p.val; else min_k = p.forward[0].forward[0].val; } for (int i = level; i >= 0; i--) { // 删除操作 if (updata[i].forward[i] != null && updata[i].forward[i].val == d) updata[i].forward[i] = updata[i].forward[i].forward[i]; } } } }
七 测试
到此这篇关于Java利用跳跃表解决双重队列问题详解的文章就介绍到这了,更多相关Java跳跃表解决双重队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!