问题引入:
某银行只有两个接待窗口,VIP 窗口和普通窗口,VIP 用户进入 VIP 窗口排队,剩下的进入普通窗口排队。现有 M 次操作,操作有四种类型,如下:
IN name V
:表示一名叫name
的用户到 VIPVIP 窗口排队OUT V
:表示 VIPVIP 窗口队头的用户离开排队IN name N
:表示一名叫name
的用户到普通窗口排队OUT N
:表示普通窗口队头的用户离开排队求 M 次操作结束后 VIP 窗口队列和普通窗口队列中的姓名。
输出描述
输出 M 次操作后 VIP 窗口队列和普通窗口队列中的姓名(从头到尾),先输出 VIP 窗口队列后输出普通窗口队列。
输入输出样例
示例 1
输入
5 IN xiaoming N IN Adel V IN laozhao N OUT N IN CLZ V
输出
Adel CLZ laozhao
-
普通队列实现
import java.util.Scanner;
public class 普通队列 {
static String Vqueue[] = new String[1000];//V队列
static int Vhead = 0;//首指针指向头元素
static int Vtail = 0;//尾指针不指向元素,前一个指针指向尾元素
static String Nqueue[] = new String[1000];//N队列
static int Nhead = 0;//首指针
static int Ntail = 0;//尾指针
//入队
static void in(String name, String type) {
if(type.contains("V")) {//V队列
Vqueue[Vtail] = name;
Vtail++;
}else {//N队列
Nqueue[Ntail] = name;
Ntail++;//队列添加一个元素,尾指针加一,但尾指针指向的元素为空
}
}
//出队
static boolean out(String type) {
if(type.contains("V")) {
if(Vhead == Vtail) {//V队列为空,不能出队
return false;
}else {
Vhead++;//头指针后移,相当于头指针前都是无效数据,相当于已删除
return true;
}
}else {
if(Nhead == Ntail) {
return false;
}else {
Nhead++;
return true;
}
}
}
//获取头元素
static String getHead(String type) {
if(type.contains("V")) {
return Vqueue[Vhead];//头元素所指向的就是第一个元素
}else {
return Nqueue[Nhead];
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int M;//一共进行M次操作
Scanner in = new Scanner(System.in);
M = in.nextInt();
while(M > 0) {
M--;
String op, name, type;
op = in.next();
if(op.contains("IN")) {
name = in.next();
type = in.next();
in(name, type);
}else {
type = in.next();
out(type);
}
}
//依次输出队列中剩下的元素
String s = getHead("V");
while(out("V")) {
System.out.println(s);
s = getHead("V");
}
s = getHead("N");
while(out("N")) {
System.out.println(s);
s = getHead("N");
}
}
}
-
循环队列实现
上述用数组实现的队列太浪费空间了,出队后的空间就废弃了,极大的浪费了空间。怎么样能让数组末尾的指针再次指向数组开头?(取模运算)
-
tail=(tail+1)% MAXSIZE
-
head=(head+1) % MAZSIZE
这样处理后,可以实现逻辑上的环形数组,充分利用了已有空间。
队满:(tail+1) % MAXSIZE == head (这里牺牲了一个空间)
对空:head == tail
import java.util.Scanner;
public class 循环队列 {
static int QueueSize = 10005;
static String Vqueue[] = new String[QueueSize];//V队列
static int Vhead = 0;//首指针不指向元素,从下一个指针开始指向头元素
static int Vtail = 0;//尾指针指向尾元素
static String Nqueue[] = new String[QueueSize];//N队列
static int Nhead = 0;
static int Ntail = 0;
//入队
static Boolean in(String name, String type) {
if(type.contains("V")) {//V队列
if((Vtail+1) % QueueSize == Vhead) {//队满则不能添加元素
return false;
}else {
Vtail = (Vtail+1) % QueueSize;
Vqueue[Vtail] = name;//尾指针指向的位置有元素,头指针指向的下一个位置才有元素
return true;
}
}else {//N队列
if((Ntail+1) % QueueSize == Nhead) {
return false;
}else {
Ntail=(Ntail+1) % QueueSize;
Nqueue[Ntail] = name;
return true;
}
}
}
//出队
static boolean out(String type) {
if(type.contains("V")) {
if(Vhead == Vtail) {//V队列为空,不能出队
return false;
}else {
Vhead = (Vhead+1) % QueueSize;//循环到末尾直接到前面
return true;
}
}else {
if(Nhead == Ntail) {
return false;
}else {
Nhead=(Nhead+1) % QueueSize;
return true;
}
}
}
//获取头元素
static String getHead(String type) {
if(type.contains("V")) {
if(Vhead == Vtail) {
return "";//空队列返回空
}else {
return Vqueue[Vhead+1];//头指针没有指向元素,后一个指针才有元素
}
}else {
if(Nhead == Ntail) {
return "";//空队列返回空
}else {
return Nqueue[Nhead+1];
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int M;//一共进行M次操作
Scanner in = new Scanner(System.in);
M = in.nextInt();
while(M > 0) {
M--;
String op, name, type;
op = in.next();
if(op.contains("IN")) {
name = in.next();
type = in.next();
in(name, type);
}else {
type = in.next();
out(type);
}
// System.out.println(Arrays.toString(Vqueue));
// System.out.println(Arrays.toString(Nqueue));
}
//依次输出队列中剩下的元素
String s = getHead("V");
while(out("V")) {
System.out.println(s);
s = getHead("V");
}
s = getHead("N");
while(out("N")) {
System.out.println(s);
s = getHead("N");
}
}
}