002_2队列_数组实现普通队列、数组实现环形队列

队列、环形队列

队列的一个使用场景:

银行排队案例------>先进先出

队列介绍:

队列是一个有序列表,可以用数组和链表实现

数组模拟队列:

数组的maxSize是该队列的最大容量

因为队列的输入和输出是分别从前后端来处理,因此需要两个变量front(头)和rear(尾)分别记录队列前后端的下标,头会随着输出改变,尾会随着输入改变

存队列---->addQueue(); 1.若尾指针往后移:rear+1,当front == rear [空] 2.将尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所指向的数据元素里,否则无法存入数据。rear == maxSize-1 [队列满]

//代码实现
import java.util.Scanner;
//数组模拟队列
public class ArrayToQueue {
	public static void main(String[] args) {
		//测试
		//创建队列
		ArrayQueue aq = new ArrayQueue(3);
		char key = ' ';//接收用户输入
		Scanner sc = new Scanner(System.in);
		boolean loop = true;
		//输出一个菜单
		while(loop) {
			System.out.println("请输入你需要进行的队列操作:");
			System.out.println("a(add):添加数据到队列");
			System.out.println("g(get):从队列中获取数据");
			System.out.println("s(show):显示队列所有数据");
			System.out.println("h(head):显示头数据");
			System.out.println("e(exit):退出程序");
			key = sc.next().charAt(0);//接收一个字符
			switch (key) {
			case 'a':
				System.out.println("请输入一个需要添加的数据:");
				int value = sc.nextInt();
				aq.addQueue(value);
				break;
			case 'g':
				try {
					int res = aq.getQueue();
					System.out.printf("获取的数据是:%d\n",res);
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}				
				break;
			case 's':
				aq.showQueue();
				break;
			case 'h':
				try {
					int res = aq.headQueue();
					System.out.printf("队列头数据是:%d\n",res);
				}catch(Exception e) {
					System.out.println(e.getMessage());
				}				
				break;
			case 'e':
				sc.close();
				loop = false;
				break;
			default:
				break;
			}
		}
		System.out.println("程序退出");		
	}
}
//数组模拟队列
class ArrayQueue{
	private int maxSize;//表示数组的最大容量
	private int front;//队列头
	private int rear;//队列尾
	private int[] arr;//用于存放数据,模拟队列	
	//创建队列的构造器
	public ArrayQueue(int arrMaxSize) {
		super();
		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) {//传入数据为n
		//1.判断队列是否满
		if(isFull()) {
			System.out.println("队列满,不能加入数据");
			return;
		}else {
			rear++;//尾部后移
			arr[rear] = n;
		}
	}
	//获取队列的数据,出队列,从头部出去
	public int getQueue() {
		//判断队列是否空
		if(isEmpty()) {
			//抛异常
			throw new RuntimeException("队列为空,不能取数据");//不用写return,因为throw也能返回
			//System.out.println("test");//throw返回了,所以报错,unreachable不能到达
		}
		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.尾索引的下一个为头索引时表示队列满**(空出一个位置作为约定)**—>(rear + 1) % maxSize == front 满

2.rear == front 空

使用数组模拟环形队列思路分析:

1.对front含义做调整,front指向第一个元素,即arr[front]---->队列第一个元素 front初始值为0

2.对rear含义做调整,rear指向最后一个元素的后一个位置,即arr[rear-1]---->队列最后一个元素**(空出一个位置作为约定)** rear初始值为0

3.当队列满时,条件是(rear + 1) % maxSize = front;【当front在0,rear在MaxSize-2的位置,预留一个位置,当rear+1即MaxSize-1对MaxSize-1取模=front即0时,为满】

4.当队列为空时,front = rear

5.当这样分析,队列中有效的数据个数:(rear + MaxSize -front) % MaxSize

6.我们可以在原来的队列上修改得到一个环形队列

在这里插入图片描述

//代码实现
import java.util.Scanner;
//数组模拟环形队列
public class ArrayToCircleQueue 
{
	public static void main(String[] args){
		//测试一把
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入需要创建的队列的长度:");
		int len = sc.nextInt();
		//创建队列
		ArrayCircleQueue atcq = new ArrayCircleQueue(len+1);
		char key = ' ';//接收用户输入
		boolean loop = true;
		//输出一个菜单
		while(loop) {
			System.out.println("请输入你需要进行的队列操作:");
			System.out.println("a(add):添加数据到队列");
			System.out.println("g(get):从队列中获取数据");
			System.out.println("s(show):显示队列所有数据");
			System.out.println("h(head):显示头数据");
			System.out.println("e(exit):退出程序");
			key = sc.next().charAt(0);//接收一个字符
			switch (key) {
			case 'a':
				System.out.println("请输入一个需要添加的数据:");
				int value = sc.nextInt();
				atcq.addQueue(value);
				break;
			case 'g':
				try {
					int res = atcq.getQueue();
					System.out.printf("获取的数据是:%d\n",res);
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}				
				break;
			case 's':
				atcq.showQueue();
				break;
			case 'h':
				try {
					int res = atcq.showHead();
					System.out.printf("队列头数据是:%d\n",res);
				}catch(Exception e) {
					System.out.println(e.getMessage());
				}				
				break;
			case 'e':
				sc.close();
				loop = false;
				break;
			default:
				break;
			}
		}
		System.out.println("程序退出");	
	}
}
class ArrayCircleQueue
{
	private int maxSize;
	private int head;
	private int rear;
	private int[] arr;
	public ArrayCircleQueue() {
		// TODO Auto-generated constructor stub
	}
	//构造器
	public ArrayCircleQueue(int arrMaxSize){
		maxSize = arrMaxSize;
		arr = new int[maxSize];
		head = 0;
		rear = 0;
	}
	//判断是否满
	public boolean isFull(){
		boolean res;
		res = ((rear + 1)%maxSize == head);
		return res;
	}
	//判断是否为空
	public boolean isEmpty(){
		return rear == head;
	}
	//添加数据到队列中
	public void addQueue(int value){
		//判断是否满
		if(isFull()){
			System.out.println("队列已经满,不能添加数据");
			return;//结束方法
		}else{
			arr[rear] = value;//因为rear代表的是尾部的后一位,所以添加的时候,rear所指向的就是添加的位置
			rear = (rear + 1) % maxSize;//添加成功,rear后移,考虑取模
		}
	}
	//获取队列数据
	public int getQueue(){
		//判断队列是否空
		if(isEmpty()){
			//通过抛异常
			throw new RuntimeException("队列空,不能取");
		}else{
			/*
			这里需要分析出head是指向队列的第一个元素
			1.先把head对应的值保存到一个临时变量
			2.将head后移,考虑取模,否则容易数组越界
			3.将临时保存的变量返回
			*/
			int value = arr[head];
			head = (head+1) % maxSize;
			return value;
		}
	}
	//显示队列的数据
	public void showQueue(){
		//遍历
		if(isEmpty()){
			System.out.println("队列为空,没有数据");
			return;//结束方法
		}else{
			/*思路:
				从head开始遍历,遍历有效数据个元素
			*/
			for(int i = head;i<(head+size());i++){
				System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);//i要取模
			}
		}
	}
	//求出当前队列有效数据个数
	public int size(){
		return (rear + maxSize - head)%maxSize;
	}
	//显示头元素
	public int showHead(){
		//判空
		if(isEmpty()){
			throw new RuntimeException("队列为空,没有头元素");
		}else{
			return arr[head];
		}
	}
}
	System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);//i要取模
		}
	}
}
//求出当前队列有效数据个数
public int size(){
	return (rear + maxSize - head)%maxSize;
}
//显示头元素
public int showHead(){
	//判空
	if(isEmpty()){
		throw new RuntimeException("队列为空,没有头元素");
	}else{
		return arr[head];
	}
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值