003--数组模拟环形队列

  1. 使用数组模拟环形队列的思路分析
  • front变量的含义做一个调整:front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值为0;
  • rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,预留一个空间做约定
  • 当队列为满时,满足条件:(rear + 1)%maxSize = front
  • 当队列为空时,满足条件:rear == front
  • 当我们这样分析,队列中有效的数据的个数为 (rear + maxSize-front)%maxSize

就是预留出一个空间,不能让他全满===只剩一个空间的时候就约定这个环形队列未满

按照我的理解来说的话,意思就是,rear指向最后一个元素的后一个位置;例如,现在这个环形队列的maxSzie=4,一开始为空,front=0,rear=0,当插入三个数后,front=0,rear指向最后一个元素的后一个位置也就是下标为3(最后一个元素下标为2),(3+1)%4 =0=front,于是判断此队列为满,此时虽然只插入三个数=====其实此时队列还有一个空间,这个空间就是我们希望空出的一个空间

  1. 代码演示,使用数组模拟环形队列
package com.xqh.queue;

import java.util.Scanner;

public class CircleArrayQueueDemo {

	public static void main(String[] args) {
		// 测试数组模拟环形队列
		CircleArray queue = new CircleArray(3);  //容量为3,但是只能存2个数据,预留一个空间,防止首尾相撞
		char key = ' '; // 接收用户输入
		Scanner scanner = new Scanner(System.in);  //扫描器
		Boolean loop = true;
		//输出一个菜单
		while(loop) {
			System.out.println("s(show):显示队列");
			System.out.println("e(exit):退出程序");
			System.out.println("a(add):添加数据到队列");
			System.out.println("g(get):从队列取出数据");
			System.out.println("h(head):查看队列头的数据");
			key = scanner.next().charAt(0); // 接收一个字符
			switch(key) {
			case 's':  //显示队列数据
				queue.showQueue();
				break;
				
			case 'a':   //添加数据
				System.out.println("输出一个数");
				int value = scanner.nextInt();
				queue.addQueue(value);
				break;
				
				
			case 'g':   //取出数据
				try {
					int res = queue.getQueue();
					System.out.printf("取出的数据是%d\n",res);
				}catch(Exception e){
					System.out.println("e.getMessage()");
				}
				break;
				
			case 'h':  //查看队列头数据,一样可能为空所以catch异常
				try {
					int res = queue.headQueue();
					System.out.printf("队列的头部数据是%d\n",res);
				}catch(Exception e){
					System.out.println("e.getMessage()");
				}
				break;
				
			case 'e':  //退出
				scanner.close();
				loop = false;
				break;
				
			default:
				break;
				
			
			}
			
		}
		System.out.println("程序退出");
		
		
		

	}

}

class CircleArray{
	private int maxSize ;  //队列最大容量
	/*front变量的含义做一个调整:front就指向队列的第一个元素,
	也就是说arr[front]就是队列的第一个元素,front的初始值为0;*/
	private int front;
	/*rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,预留一个空间做约定,初始值为0*/
	private int rear;
	private int[] arr;   //该数组用于存放数据,模拟队列
	
	public CircleArray(int arrMaxSize) {
		maxSize = arrMaxSize;
		arr = new int[maxSize];  //队列数组
	}
	
	//判断是否为满,当队列为满时,满足条件:(rear + 1)%maxSize = front 
	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;
			}
			//直接将数据加入,因为rear本身就是指向最后一个元素的后一个位置,所以添加的位置就是rear所指向的位置
			arr[rear] = n ;
			//rear指针后移一位,但是圆形队列,可能已经到底了,后移可能移到开头(0)去了,所以取模(这就是环形队列与队列的区别)
			rear=(rear+1)%maxSize;
		}
		
		
	//从队列取出数据
		public int getQueue() {
			//判断队列是否空
			if(isEmpty()) {
				//抛出异常
				throw new RuntimeException("队列空,不能取数据~");
			}
			//front是指向队列的第一个元素,取出第一个元素以下步骤
			//1.先把front对应的值保留到一个临时变量;(为什么不直接返回--->因为直接返回的话就没机会再给front后移了)
			//2.将front后移,考虑取模
			//3.将临时保存的变量返回
			int value = arr[front];
			front = (front+1)%maxSize;
			return value;
			
		}
		

		//显示队列的所有数据
		public void showQueue() {
			//遍历
			if(isEmpty()) {
				System.out.println("队列是空的,没有数据~");
				return;
			}
			//思路:从front开始遍历,遍历多少个有效数据
			for(int i = front;i < front+size();i++) {
				System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i % maxSize]);
			}
		}
	
	
		//获取队列有效数据的个数
		public int size() {
			return (rear+maxSize-front)%maxSize;
		}
		
		
		//显示队列的头数据,注意不是取出数据
		public int headQueue() {
			if(isEmpty()) {
				throw new RuntimeException("队列是空的,没有数据~");
			}
			return arr[front] ;   //这里只是显示这个头数据,但是指针并没有改变,所以没有取出操作,front指向的是队列头部的前一个位置,所以要+1
		}
	
	
	
	
	
	
	
}

你可能感兴趣的:(Java数据结构与算法,java,数据结构,jvm)