队列


队列 (先入先出原则)

  1. 如果说链表和顺序表是对数据的存取位置的组织方式,那么队列就是一种对于存取方式限制的组织方式。换一种方式描述的话就是,队列既可以采用链表来表示,也可以采用数组(线性表)来表示,我们限制的是对于存放数据的存取方式。

  2. 出从队首出,入插入队尾

  3. 队列:只允许在一端进行插入操作,而另一端进行删除操作的线性表。

  4. 空队列:不含任何数据元素的队列。

  5. 允许插入(也称入队、进队)的一端称为队尾,允许删除(也称出队)的一端称为队头。

    例题:

    银行排队问题, 银行只有两个接待窗口,VIP 窗口和普通窗口,VIP 用户进入 VIP 用户窗口,剩下的进入普通窗口排队。

    现在有以下输入:

    第一行 M 次操作(M<1000)
    
    第二行 到 第M+1行 输入操作
    
    格式:   IN name V
            OUT V
            IN name2 N
            OUT N
            即 第一个字符串为操作 是IN进入排队和OUT 出队
                IN 排队 跟着两个字符串为姓名和权限V或N
                OUT 为出队即完成操作,V和N代表那个窗口完成了操作
    
    输出:M次操作后V队列和N队列中姓名,先输出V队列后输出N队列。
    
    样例:
    
    输入:
    
    5
    IN xiaoming N
    IN Adel V
    IN laozhao N
    OUT N
    IN CLZ V
    
    输出:
    
    Adel
    CLZ
    laozhao
    

    分析思路:

    1. 第一步,创建两个队列,以及两个队列的首尾指针
    2. 第二步,我们要写入队函数:按照队列的定义使用尾指针模拟即可;设置 Type 位来表示是哪一个队列;Type为V,那么Name进入V队列;Type为N,那么Name进入N队列;
    3. 第三步,我们要写出队函数:按照队列的定义使用头指针模拟即可;仍需设置 Type 位来表示是哪一个队列
    4. 第四步,写出获取队头元素的代码,队列我们只关心谁排在第一个;按照队列的定义使用头指针模拟即可;仍需设置 Type 位来表示是哪一个队列;
    5. 主函数代码:
    输入M
    循环M次: 
    
         输入操作符OP
         OP为IN,则输入name和Type
         OP为Out,则输入Type

        根据执行OP执行in或out操作

    若队列V不为空,执行以下操作:
        输出队首元素,队首出队
        直到为空为止

    若队列N不为空,执行以下操作:
        输出队首元素,队首出队
        直到为空为止

代码实现(用数组模拟队列):

package 队列;

import java.util.Scanner;

public class Quque_01 {
	
	//1. 创建两个队列,以及两个队列的首尾指针
	 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; // 尾指针
	
	//2.入队函数: 尾指针模拟 设置 Type 位来表示是哪一个队列
	  static void in(String name,String type) {
		  if(type.contains("V")) {
			  Vqueue[Vtail++] = name;
		  }
		  else {
			  Nqueue[Ntail++] = name;
		  }
	  }
	//3.出队函数:头指针模拟  设置 Type 位来表示是哪一个队列
	  static boolean out(String type) {
		  if(type.contains("V")) {
			  //先判断队列是否为空 为空的条件就是首尾指针相等
			  if(Vhead == Vtail) {
				  return false;
			  }
			  else {
				  Vhead++;
				  return true;
			  }
		  }
		  else {
			  if(Nhead == Ntail) {
				  return false;
			  }
			  else {
				  Nhead++;
				  return true;
			  } 
		  }
	  }
	  
	  //4.获取队头元素
	  static String getHead(String type) {
		  if(type.contains("V")) {
			  return Vqueue[Vhead];
		  }
		  else {
			  return Nqueue[Nhead];
		  }
	  }
	
	public static void main(String[] args) {		 
		 Scanner  scanner = new Scanner(System.in);
		 //输入操作次数
		 int m = scanner.nextInt();
		 while(m>0) {
			 m--;
			// 输入操作符 若为IN,则输入name和Type; 若为Out,则输入Type
			 String opString = scanner.next();
			 if(opString.contains("IN")){
				 String name  = scanner.next();
				 String type  = scanner.next();
				 in(name, type);
			 }
			 else {
				 String type  = scanner.next();
				 out(type);
			 }
		 }
		 
		 //若队列V不为空,输出队首元素,队首出队,直到为空为止
		 String v = getHead("V");
		 while(out("V")) {//此处显示了出队函数中的功能:判断是否空 头指针后移 以及返回类型是boolean
			 System.out.println(v);
			 v = getHead("V");//获取下一个队首元素
		 }
		 
		//若队列N不为空,输出队首元素,队首出队,直到为空为止
		 String n= getHead("N");
		 while(out("N")) {
			 System.out.println(n);
			 n = getHead("N");
		 }	 
	}
}

使用java中已经定义好的队列数据结构(用数组模拟是为了更好地了解队列的实现原理,以后用到队列时,直接调用Queue)

定义方式:

Queue queue = new LinkedList();

部分成员函数(包括继承的):

add(): 增加一个元索,如果队列已满,则抛出一个异常
remove():移除并返回队列头部的元素,如果队列为空,则抛出一个异常
element():返回队列头部的元素,如果队列为空,则抛出一个异常
offer():添加一个元素并返回 true,如果队列已满,则返回 false
put(): 添加一个元素, 如果队列满,则阻塞
take(): 移除并返回队列头部的元素,如果队列为空,则阻塞
size(): 返回队列长度。
peek(): 返回队列头部的元素,如果队列为空,则返回 null
poll(): 移除并返问队列头部的元素,如果队列为空,则返回 null

代码实现:

package 队列;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Quque_02 {
	// 1. 创建两个队列
	static Queue vqueue = new LinkedList<>();
	static Queue nqueue = new LinkedList<>();

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		// 输入操作次数
		int m = scanner.nextInt();
		while (m > 0) {
			m--;
			// 输入操作符 若为IN,则输入name和Type; 若为Out,则输入Type
			String opString = scanner.next();
			if (opString.contains("IN")) {
				String name = scanner.next();
				String type = scanner.next();
				if (type.contains("V")) {
					vqueue.offer(name);// offer():添加一个元素并返回 true,如果队列已满,则返回 false
				} else {
					nqueue.offer(name);
				}
			} else {
				String type = scanner.next();
				if (type.contains("V")) {
					vqueue.poll();// poll(): 移除并返问队列头部的元素,如果队列为空,则返回 null
				} else {
					nqueue.poll();
				}
			}

		}
		
		//输出:
		//若队列V不为空,输出队首元素,队首出队,直到为空为止
		while(vqueue.size()!=0) {
			System.out.println(vqueue.poll());
		}
		
		//若队列N不为空,输出队首元素,队首出队,直到为空为止
		while(nqueue.size()!=0) {
			System.out.println(nqueue.poll());
		}
	}
}