Java利用跳躍表解決雙重隊列問題詳解
一 問題描述
銀行的每個客戶都有一個正整數(shù)標(biāo)識 K,到銀行請求服務(wù)時將收到一個正整數(shù)的優(yōu)先級 P 。銀行經(jīng)理提議打破傳統(tǒng),在某些時候調(diào)用優(yōu)先級最低的客戶,而不是優(yōu)先級最高的客戶。系統(tǒng)將收到以下類型的請求:
① 0,系統(tǒng)需要停止服務(wù)。
② 1 K P,將客戶 K 及優(yōu)先級 P 添加到等待列表中。
③ 2,為優(yōu)先級最高的客戶提供服務(wù),并將其從等待名單中刪除。
④ 3,為優(yōu)先級最低的客戶提供服務(wù),并將其從等待名單中刪除。
二 輸入
輸入的每一行都包含一個請求,只有最后一行包含停止請求(代碼0)。假設(shè)有請求在列表中包含新客戶(代碼1),在同一客戶的列表中沒有其他請求或有相同的優(yōu)先級,標(biāo)識符 K 總是小于10^6 ,優(yōu)先級 P 總是小于10^7 。一個客戶可以多次到銀行請求服務(wù),但是每次都獲得不同的優(yōu)先級。
三 輸出
對代碼為 2 或 3 的每個請求都單行輸出所服務(wù)客戶的標(biāo)識。若請求在等待列表為空時到達,則輸出 0。
四 輸入和輸出樣例
1 輸入樣例
2
1 20 14
1 30 3
2
1 10 99
3
2
2
0
2 輸出樣例
0
20
30
10
0
五 分析和設(shè)計
本問題包括插入、刪除優(yōu)先級最高元素和刪除優(yōu)先級最低元素等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;
}
// 按規(guī)則選擇數(shù)據(jù)應(yīng)該在哪層插入
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; // 記錄搜索過程中各級走過的最大節(jié)點位置
}
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) // 要插入的層 > 現(xiàn)有層數(shù)
level = lay;
Find(val); //查詢
s = new Node(); // 創(chuàng)建一個新節(jié)點
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) // 刪除唯一節(jié)點
{
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];
}
}
}
}七 測試

到此這篇關(guān)于Java利用跳躍表解決雙重隊列問題詳解的文章就介紹到這了,更多相關(guān)Java跳躍表解決雙重隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java?Collections.sort()實現(xiàn)List排序的默認方法和自定義方法
這篇文章主要介紹了Java?Collections.sort()實現(xiàn)List排序的默認方法和自定義方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2017-06-06
InputStreamReader和BufferedReader用法及實例講解
這篇文章主要介紹了InputStreamReader和BufferedReader用法及實例講解的相關(guān)資料,需要的朋友可以參考下2015-12-12
SpringSecurity根據(jù)自定義異常返回登錄錯誤提示信息(賬戶鎖定)
本文介紹了在SpringSecurity中根據(jù)自定義異常返回登錄錯誤提示信息的方法,特別是在賬戶鎖定時,通過記錄輸錯次數(shù)、重寫校驗方法并拋出自定義異常,感興趣的可以了解一下2025-01-01
java?LeetCode刷題稍有難度的貪心構(gòu)造算法
這篇文章主要為大家介紹了java?LeetCode刷題稍有難度的貪心構(gòu)造題解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
WebSocket實現(xiàn)數(shù)據(jù)庫更新時前端頁面刷新
這篇文章主要為大家詳細介紹了WebSocket實現(xiàn)數(shù)據(jù)庫更新時前端頁面刷新,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-04-04
java使用RandomAccessFile類基于指針讀寫文件實例代碼
這篇文章主要介紹了java使用RandomAccessFile類基于指針讀寫文件實例代碼,具有一定參考價值,需要的朋友可以了解下。2017-10-10

