队列
队列是一个有序列表,可以用数组或是链表来实现。
遵循先进先出的原则,即先存入队列的数据,要先取出,后存入的要后取出
数组模拟队列
实现的思路
- 队列是有序列表,使用数组来存储队列的数据,则需要创建数组
ArrayQueue arrayQueue = new ArrayQueue(maxSize);,其中maxSize是该队列的最大值,ArrayQueue是实现队列的类。 - 因为队列的输入输出分别是从队列的前后端存入和取出,因此需要两个变量
front和rear分别指向队列前后端的下标。front随着数据输出而向后移动,rear随着数据的输入而进行移动。初始化时,front和rear变量都定义为 -1 - 当数据存入队列时,首先将尾指针向后移:rear + 1,判断尾指针
rear是否小于队列的最大下标值 maxSize - 1,如果是则将数据存入 rear 所指的数组元素中,否则无法存入数据。当 rear == maxSize - 1 则表示队列满。 - 当数据从队列取出时,首先判断队列是否为空,front == rear 表示队列为空,若不为空则将 front + 1,取出数组对应下标的值。
实现代码
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.print("请输入一个数字:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int result = arrayQueue.getQueue();
System.out.println("取出的数据是:" + result);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int result = arrayQueue.getFrontData();
System.out.println("队列头数据是:" + result);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
System.out.println("程序结束");
loop = false;
default:
System.out.println("输入错误,请重新输入");
break;
}
}
}
}
// 使用数组模拟队列
class ArrayQueue{
private int maxSize; // 数组最大容量
private int front; // 队列头
private int rear; // 队列尾
private int[] array; // 该数组用于存储数据,模拟队列
// 模拟队列的构造器
public ArrayQueue(int arraySize){
maxSize = arraySize;
front = -1; // 指向队列头部,分析出front是指向队列头的前一个位置
rear = -1; // 指向队列尾部,指向队列尾部的数据(即队列的最后一个位置)
array = new int[maxSize];
}
// 判断队列是否已满
public Boolean isFull(){
return rear == maxSize - 1;
}
// 判断队列是否为空
public boolean isEmpty(){
return front == rear;
}
// 添加数据到队列
public void addQueue(int n){
if (isFull()){
System.out.println("队列已满,无法添加数据");
return;
}
rear++;
array[rear] = n; // array[++rear]
}
// 获取队列数据,出队列
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法获取数据...");
}
front++;
return array[front];
}
// 遍历队列数据
public void showQueue(){
if (isEmpty()){
System.out.println("队列为空,没有数据...");
return;
}
for (int i = 0; i < array.length; i++){
System.out.printf("array[%d] = %d ", i ,array[i]);
}
System.out.println();
}
// 显示队列的头数据,不是取出数据
public int getFrontData(){
if (isEmpty()){
throw new RuntimeException("队列为空,头数据为空");
}
int i = array[++front];
front--;
return i;
}
}
数组模拟环形队列
实现的思路
将数组看作一个环形,利用取模的方式来实现。具体思路如下:
- front变量指向队列的第一个元素,即array[front]表示队列的第一个值,front的初始值定义为 0
- rear变量指向队列的最后一个元素,并且空出一个位置作为缓冲区,rear的初始值定义为 0
- 存入数据时,首先判断队列是否已满,判断条件是
(rear + 1) % maxSize == front,如果未满则在rear所指的下标位置添加数据,并且将rear变量向后移动,由于是环形队列,考虑溢出的情况需要取模(rear + 1) % maxsize - 取出数据时,判断队列是否为空,判断条件是 front == rear。不为空则取出当前front下标对应的值。
- 环形队列中有效数据个数:
(rear + maxSize - front) % maxSize
实现代码
public class CircleArrayQueueDemo {
public static void main(String[] args) {
CircleArrayQueue arrayQueue = new CircleArrayQueue(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("y(head):有效数据个数");
System.out.println("e(exit):退出程序");
key = scanner.next().charAt(0); // 接收一个字符
switch (key){
case 's':
arrayQueue.showQueue();
break;
case 'a':
System.out.print("请输入一个数字:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'y':
int i = arrayQueue.size();
System.out.println("有效个数是:" + i);
break;
case 'g':
try {
int result = arrayQueue.getQueue();
System.out.println("取出的数据是:" + result);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int result = arrayQueue.getFrontData();
System.out.println("队列头数据是:" + result);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
System.out.println("程序结束");
loop = false;
default:
System.out.println("输入错误,请重新输入");
break;
}
}
}
}
class CircleArrayQueue{
private int maxSize; // 数组最大容量
// front 变量的含义:front指向队列的第一个元素,也就是arr[front],front的初始值为0
private int front; // 队列头
// rear 变量的含义:rear指向队列的最后一个元素的最后一个位置,空出一个空间做缓冲,rear的初始值为0
private int rear; // 队列尾
private int[] array; // 该数组用于存储数据,模拟队列
// 模拟队列的构造器
public CircleArrayQueue(int arraySize){
maxSize = arraySize;
front = 0; // 指向队列头部,分析出front是指向队列头的前一个位置
rear = 0; // 指向队列尾部,指向队列尾部的数据(即队列的最后一个位置)
array = new int[maxSize];
}
// 判断队列是否已满
public Boolean isFull(){
return (rear + 1) % maxSize == front;
}
// 判断队列是否为空
public boolean isEmpty(){
return front == rear;
}
// 添加数据到队列
public void addQueue(int n){
if (isFull()){
System.out.println("队列已满,无法添加数据");
return;
}
array[rear] = n;
// 将rear后移,必须考虑取模,环形队列可以会数组越界
rear = (rear + 1) % maxSize;
}
// 获取队列数据,出队列
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法获取数据...");
}
int i = array[front];
front = (front + 1) % maxSize;
return i;
}
// 遍历队列数据
public void showQueue(){
if (isEmpty()){
System.out.println("队列为空,没有数据...");
return;
}
// 重要,环形队列循环查看数据
for (int i = front; i < front + size(); i++){
System.out.printf("array[%d] = %d\n", i % maxSize ,array[i % maxSize]);
}
System.out.println();
}
// 求出当前数组的有效数据个数
public int size(){
return (rear + maxSize - front) % maxSize;
}
// 显示队列的头数据,不是取出数据
public int getFrontData(){
if (isEmpty()){
throw new RuntimeException("队列为空,头数据为空");
}
return array[front];
}
}
上述代码是存在一个空位置作为缓冲区,下面没有缓冲区并实现环形队列
public class CircleArrayQueueDemo {
public static void main(String[] args) {
CircleArrayQueue arrayQueue = new CircleArrayQueue(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("y(head):有效数据个数");
System.out.println("e(exit):退出程序");
key = scanner.next().charAt(0); // 接收一个字符
switch (key){
case 's':
arrayQueue.showQueue();
break;
case 'a':
System.out.print("请输入一个数字:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'y':
int i = arrayQueue.size();
System.out.println("有效个数是:" + i);
break;
case 'g':
try {
int result = arrayQueue.getQueue();
System.out.println("取出的数据是:" + result);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int result = arrayQueue.getFrontData();
System.out.println("队列头数据是:" + result);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
System.out.println("程序结束");
loop = false;
default:
System.out.println("输入错误,请重新输入");
break;
}
}
}
}
class CircleArrayQueue{
private int maxSize; // 数组最大容量
private int front; // 队列头
private int rear; // 队列尾
private int[] array; // 该数组用于存储数据,模拟队列
// 模拟队列的构造器
public CircleArrayQueue(int arraySize){
maxSize = arraySize;
front = -1; // 指向队列头部,分析出front是指向队列头的前一个位置
rear = -1; // 指向队列尾部,指向队列尾部的数据(即队列的最后一个位置)
array = new int[maxSize];
}
// 标志位 0 表示 rear == front 为空,1 表示 rear == front 为满
int i = 0;
// 判断队列是否已满
public Boolean isFull(){
if (rear == -1){
return false;
}
if (rear + 1 == maxSize && front == -1){
return true;
}
if (i == 1 && rear == front){
return true;
}
return false;
}
// 判断队列是否为空
public boolean isEmpty(){
return i == 0 && front == rear;
}
// 添加数据到队列
public void addQueue(int n){
if (isFull()){
System.out.println("队列已满,无法添加数据");
return;
}
// 将rear后移,必须考虑取模,环形队列可以会数组越界
if (++rear >= maxSize){
i = 1;
rear %= maxSize;
}
array[rear] = n;
}
// 获取队列数据,出队列
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法获取数据...");
}
if (++front == maxSize){
i = 0;
front = -1;
}
return array[front];
}
// 遍历队列数据
public void showQueue(){
if (isEmpty()){
System.out.println("队列为空,没有数据...");
return;
}
if (front == -1){
for (int i = front + 1; i <= rear; i++){
System.out.printf("array[%d] = %d\n", i % maxSize ,array[i % maxSize]);
}
}else{
for (int i = front + 1; i <= front + size(); i++){
System.out.printf("array[%d] = %d\n", i % maxSize ,array[i % maxSize]);
}
}
System.out.println();
}
// 求出当前数组的有效数据个数
public int size(){
if (front == -1){
return rear+1;
}
if (rear == front && i == 1){
return maxSize;
}
return (rear + maxSize - front) % maxSize;
}
// 显示队列的头数据,不是取出数据
public int getFrontData(){
if (isEmpty()){
throw new RuntimeException("队列为空,头数据为空");
}
int i = array[++front];
front--;
return i;
}
}