文章目录

  • 1.模拟普通队列
  • 队列:先进先出,后进后出; 即尾进头出
  • 应用: 银行叫号系统
  • 会出现一个问题: 该数组只能使用一次,数组满后就算是你此刻取了数据也无法再添加进去,同样,当把数据全部取出来之后,就算添加了数据也是无法取出来的.即没有达到复用的效果.
  • (解决此问题参考 2.模拟环形队列 取模完成)
  • 思路:
  • 1.1 创建ArrayQueue类, 该类中包含 队列的构造器,判断队列是否满,判断队列是否为空,添加数据到队列,出队列,显示数据 这些操作
  • 1.2 创建测试类
  • 1.3 效果图
  • 2.数组模拟环形队列
  • 思路:
  • 代码:
  • 和第一个代码的不同地方
  • 效果图


1.模拟普通队列

队列:先进先出,后进后出; 即尾进头出

应用: 银行叫号系统

会出现一个问题: 该数组只能使用一次,数组满后就算是你此刻取了数据也无法再添加进去,同样,当把数据全部取出来之后,就算添加了数据也是无法取出来的.即没有达到复用的效果.

(解决此问题参考 2.模拟环形队列 取模完成)

思路:

private int maxSize; //表示数组最大容量
private int front; //队列头
private int rear; //队列尾
private int[] arr; //该数组用于存放数据,模拟队列
* front是指向队列头的前一个位置
* rear是指向队列的尾部的数据,即就是队列最后一个数据
 注意带 * 的这里,思路 与 数组实现环形队列的变化

1.1 创建ArrayQueue类, 该类中包含 队列的构造器,判断队列是否满,判断队列是否为空,添加数据到队列,出队列,显示数据 这些操作

class ArrayQueue{
	private int maxSize; //表示数组最大容量
	private int front; //队列头
	private int rear; //队列尾
	private int[] arr; //该数组用于存放数据,模拟队列
	
	//创建队列的构造器
	public ArrayQueue(int arrMaxSize) {
		maxSize = arrMaxSize;
		arr = new int[maxSize];
		front = -1;  //指向队列头部,分析出 front是指向队列头的前一个位置
		rear = -1;  //指向队列尾部,分析出 rear是指向队列的尾部的数据,即就是队列最后一个数据
	}
	
	//判断队列是否满
	public boolean isFull() {
		return rear == maxSize -1;
	}
	
	//判断队列是否为空
	public boolean isEmpty() {
		return rear == front;
	}
	
	//添加数据到队列
	public void addQueue(int n) {
		if(isFull()) {
			System.out.println("队列满,不能加入数据");
			return;
		}
		rear ++;
		arr[rear] = n;
	}
	
	//出队列
	public int getQueue() {
		if(isEmpty()) {
			 //通过抛出异常处理
			 throw new RuntimeException("队列为空,不能取出数据");
		}
		front ++; //front 进行后移
		return arr[front];
		
		
	}
	
	//显示数据
	public void showQueue() {
		//遍历
		if(isEmpty()) {
			System.out.println("队列为空,没有数据");
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.printf("arr[%d]=%d\n",i,arr[i]);
		}
	}
	
	
	//显示队列的头数据,注意不是取出数据
	public int headQueue() {
		if (isEmpty()) {
			throw new RuntimeException("队列为空,不能取出数据");
			
		}
		return arr[front+1];
	}
	
	
	
}

1.2 创建测试类

package com.beyond.queue;

import java.util.Scanner;

public class ArrayQueueDemo {
	public static void main(String[] args) {
		//测试
		//创建一个队列
		ArrayQueue arrayQueue = new ArrayQueue(3);
		char key = ' '; //接收用户输入
		Scanner scanner = new Scanner(System.in);
		boolean loop = true;
		
		//输出一个菜单
		while(loop) {
			System.out.println("s(show):显示队列");
			System.out.println("a(add):添加数据到队列");
			System.out.println("g(get):从队列中取出数据");
			System.out.println("h(head):查看队列头的数据");
			System.out.println("e(exit):程序退出");
			key = scanner.next().charAt(0); //接收一个字符
			switch (key) {
			case 's':
				arrayQueue.showQueue();
				break;
			case 'a':
				System.out.println("输入添加的数:");
				arrayQueue.addQueue(scanner.nextInt());
				break;
			case 'g':
				try {
					System.out.printf("取出的数据是%d\n",arrayQueue.getQueue());
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}
				break;
			case 'h':
				try {
					System.out.printf("队列头的数据是%d\n",arrayQueue.headQueue());
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}
				break;
			case 'e':
				scanner.close();
				loop = false;
				break;
			default:
				break;
			}
		}
		System.out.println("程序退出!");
	}

}

1.3 效果图

java 数组分组使用多线程_java 数组分组使用多线程

2.数组模拟环形队列

思路:

1.front 变量的含义做了改变: front 就是指向队列的第一个元素,
	也就是说 arr[front]就是队列的第一个元素(这里front是数组下标)
		front的初始值 = 0
2.rear 变量的含义做了改变: 
		rear 指向队列的最后一个元素的后一个位置
		(即数组下标+1,变成位下标,[这里 rear是数组下标 ,(rear+1)是位下标] ),
		因为数组是从0下标开始,位下标是从1开始,而maxSize是数组元素个数,即位下标
	rear的初始值 = 0
3. 当队列满时, 条件是 (rear+1) % maxSize == (front +1)-1
4. 队列为空的条件是 rear == front
5. 这样的情况下, 队列中有效的数据个数: 
		 [(rear+1)+ maxSize -(front+1)]%maxSize  
        		即 (rear+maxSize-front)%maxSize

代码:

package com.beyond.queue;

import java.util.Scanner;

public class CircleArrayQueue {
	public static void main(String[] args) {
		// 测试
		// 创建一个环形队列
		CircleArray circleArray = new CircleArray(4);  //因为这里的 rear实际是 位下标(数组rear+1得到),因此数组实际 length 为 maxSize -1 
		char key = ' '; // 接收用户输入
		Scanner scanner = new Scanner(System.in);
		boolean loop = true;

		// 输出一个菜单
		while (loop) {
			System.out.println("s(show):显示队列");
			System.out.println("a(add):添加数据到队列");
			System.out.println("g(get):从队列中取出数据");
			System.out.println("h(head):查看队列头的数据");
			System.out.println("e(exit):程序退出");
			key = scanner.next().charAt(0); // 接收一个字符
			switch (key) {
			case 's':
				circleArray.showQueue();
				break;
			case 'a':
				System.out.println("输入添加的数:");
				circleArray.addQueue(scanner.nextInt());
				break;
			case 'g':
				try {
					System.out.printf("取出的数据是%d\n", circleArray.getQueue());
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}
				break;
			case 'h':
				try {
					System.out.printf("队列头的数据是%d\n", circleArray.headQueue());
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}
				break;
			case 'e':
				scanner.close();
				loop = false;
				break;
			default:
				break;
			}
		}
		System.out.println("程序退出!");
	}

}

class CircleArray {
	private int maxSize; // 表示数组最大容量

	// 1.front 变量的含义做了改变: front 就是指向队列的第一个元素,也就是说 arr[front]就是队列的第一个元素(这里front是数组下标)
//	front的初始值 = 0
	private int front; // 队列头
	// 2.rear 变量的含义做了改变: rear 指向队列的最后一个元素的后一个位置(即数组下标+1,变成位下标,[这里
	// rear=(rear+1),是位下标],前面括号里rear其实是数组下标
	// ),因为数组是从0下标开始,位下标是从1开始,而maxSize是数组元素个数,即位下标
//	 rear的初始值 = 0
	private int rear; // 队列尾
	private int[] arr; // 该数组用于存放数据,模拟环形队列

	// 创建构造器
	public CircleArray(int arrMaxSize) {
		maxSize = arrMaxSize;
		arr = new int[maxSize];
		front = 0; // 不写也行,int 默认是 0
		rear = 0; // 不写也行,int 默认是 0
	}

	// 判断队列是否满
	public boolean isFull() {
		return (rear + 1) % maxSize == front;
	}

	// 判断队列是否为空
	public boolean isEmpty() {
		return rear == front;
	}

	// 添加数据到队列
	public void addQueue(int n) {
		if (isFull()) {
			System.out.println("队列满,不能加入数据");
			return;
		}
		// 直接将数据加入
		arr[rear] = n;
		rear = (rear + 1) % maxSize;
	}

	// 出队列
	public int getQueue() {
		if (isEmpty()) {
			// 通过抛出异常处理
			throw new RuntimeException("队列为空,不能取出数据");
		}
		// 这里需要分析 出 front 是指向队列的第一个元素
		// 1. 先把front 对应的值保留在临时变量
		// 2. 将 front 后移, 考虑取模
		// 3. 将临时的变量返回
		int a = arr[front];
		front = (front + 1) % maxSize;
		return a;

	}

	// 显示数据
	public void showQueue() {

		if (isEmpty()) {
			System.out.println("队列为空,没有数据");
			return;
		}

		// 遍历思路: 从front开始,遍历 队列中有效的数据个数: (rear+maxSize-front) % maxSize
		for (int i = front; i < front+count(); i++) {
			System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
		}
	}

	// 输出环形队列的有效个数
	public int count() {
		return (rear + maxSize - front) % maxSize;
	}

	// 显示队列的头数据,注意不是取出数据
	public int headQueue() {
		if (isEmpty()) {
			throw new RuntimeException("队列为空,不能取出数据");

		}
		return arr[front];
	}

}

和第一个代码的不同地方

java 数组分组使用多线程_队列_02


java 数组分组使用多线程_数据结构_03


java 数组分组使用多线程_java_04


java 数组分组使用多线程_算法_05


java 数组分组使用多线程_队列_06


java 数组分组使用多线程_数据结构_07

效果图

java 数组分组使用多线程_算法_08