数据结构之队列

队列

一、使用场景:银行排队系统

二、概念

a.队列是一个有序列表,可以用数组或者链表来实现。
b.遵循先入先出的原则
c.数组队列示意图,maxSize最大容量、Queuce类、front队列前端,rear队列后端,front随数据输出而变化,rear随数据输入而变化
在这里插入图片描述

d.当我们将数据存入队列时,称为,“addQueue”它需要处理两个步骤
①将尾指针往后移,rear+1 ,当front==rear时队列为空
②若尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所指的数组元素中,否则无法存入数据,rear==maxSize-1时队列满,无法存入数据。

三、代码实现

import java.util.Scanner;
public class QueueDemo {
	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("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':
					arrayQueue.showQueue();
					break;
				case 'a':
					System.out.println("请输入一个值");
					int i = scanner.nextInt();
					arrayQueue.addQueue(i);
					break;
				case 'g':
					try {
						int res = arrayQueue.getQueue();
						System.out.printf("取出的数据%d\n",res);
					}catch (Exception e){
						System.out.println(e.getMessage());
					}
					break;
				case 'h':
					try {
						int headQueue = arrayQueue.headQueue();
						System.out.printf("队列头数据%d\n",headQueue);
						break;
					}catch (Exception e){
						System.out.println(e.getMessage());
					}
					break;
				case 'e'://退出
					scanner.close();
					loop=false;
					break;
				default:
					break;
			}
		}
		System.out.printf("程序退出啦啦啦");

	}


}
	//数组模拟队列
class ArrayQueue {
	private int maxSize;//数组最大容量
	private int front ;//队列头,分析出front是指向队列头的前一个位置
	private int rear;//队列尾,指向队列尾的数据,即队列最后一个数据
	private int[] arr; //该数组用于存放数据,模拟队列

	//创建队列构造器
	public ArrayQueue(int arrMaxSize){
		maxSize=arrMaxSize;
		arr=new int[maxSize];
		front=-1;
		rear=-1;
	}
	//判断队列是否满
	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)、front变量含义做一个调整:指向队列第一个元素,arr[front]就是队列的第一个元素,front初始值为0
2)、rear变量含义做一个调整:指向队列的最后一个元素的后一个位置,因为我们希望空出一个空间作为约定,rear的初始值为0
3)、当队列满时,条件是,(rear+1)%maxSize=front【满】
4)、当队列为空时,条件是rear=front
5)、队列中有效的数据个数(rear+maxSize-front)%maxSize
6)、我们就可以在原来的队列上修改得到一个环形队列

③、环形队列代码实现

import java.util.Scanner;
public class CircleArrayQueueDemo {
	public static void main(String[] args) {
		//测试
		CircleArray arrayQueue = new CircleArray(4);//设置为4,有效数据最大是3,约定值在不断的变化
		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':
					arrayQueue.showQueue();
					break;
				case 'a':
					System.out.println("请输入一个值");
					int i = scanner.nextInt();
					arrayQueue.addQueue(i);
					break;
				case 'g':
					try {
						int res = arrayQueue.getQueue();
						System.out.printf("取出的数据%d\n",res);
					}catch (Exception e){
						System.out.println(e.getMessage());
					}
					break;
				case 'h':
					try {
						int headQueue = arrayQueue.headQueue();
						System.out.printf("队列头数据%d\n",headQueue);
						break;
					}catch (Exception e){
						System.out.println(e.getMessage());
					}
					break;
				case 'e'://退出
					scanner.close();
					loop=false;
					break;
				default:
					break;
			}
		}
		System.out.printf("程序退出啦啦啦");
	}
}
class CircleArray{
	private int maxSize;//数组最大容量
	private int front ;//队列头,指向队列第一个元素,arr[front]就是队列的第一个元素,front初始值为0
	private int rear;//队列尾,指向队列的最后一个元素的后一个位置,因为我们希望空出一个空间作为约定,rear的初始值为0。
	private int[] arr; //该数组用于存放数据,模拟队列

	public CircleArray(int arrMaxSize){
		maxSize=arrMaxSize;
		arr=new int[maxSize];
	}
	//判断队列是否满
	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=(rear+1)%maxSize;
	}
	//取出数据
	public int getQueue(){
		if (isEmpty()) {
			//通过抛出异常来处理
			throw new RuntimeException("队列为空不能取数据");
		}
		//这里需要分析出front是指向队列的第一个元素,首相,把front对应的值保存到一个临时的变量,将front后移,考虑取模,将临时保存的变量返回
		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];
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值