用java数组实现普通队列
队列的特点:
- 先进先出
- 进入队列时从队列尾部进入,头部指针不发生变化,尾部指针向后一位
- 出队列时从队列头部出,头部指针向后一位,尾部指针不变
四个变量:
- max 表示队列容量
- arr 表示队列
- rear 尾部指针,初始为-1。指向队列最后一个元素,arr[rear]=最后一个元素
- front 头部指针,初始为-1。指向队列第一个元素的前一个位置,arr[front+1]=第一个元素
判断队列是否满:rear=max-1 比如队列容量是4,数组的下标最大就是3,而因为rear指向的是最后一个数据,rear也是3,这时候就满了。
判断队列是否空:front=rear 因为rear是最后一个数的位置,front是第一个数前一个位置,如果此时只剩一个数,front指向rear前一个位置,如果再出队列,front就会和rear相等,此时就空了。
存在的问题:假溢出。因为队列顺序往前,几个数据出队列以后留下的空白就没办法再加入数据了,因为加数据是rear指针再增加就会越界,队列会假满。所以造成假溢出的关键其实是rear=max-1
代码实现
class ArrayQueue{
//队列容量
private int max;
//队列头,指向队列第一个元素的前一个元素
private int front;
//队列尾,指向队列最后一个元素
private int rear;
//队列本体
private int[] arr;
public ArrayQueue(int max){
this.max=max;
this.front=-1;
this.rear=-1;
arr=new int[max];
}
//判断队列是否满
public boolean isFull(){
return rear==max-1;
}
//判断队列是否空
public boolean isEmpty(){
return front==rear;
}
//进队列
public void in(int n){
if(!isFull()){
rear++;
arr[rear]=n;
}else {
System.out.println("队列已满");
}
}
//出队列
public int out(){
if(!isEmpty()){
front++;
return arr[front];
}else {
front=-1;
rear=-1;
throw new RuntimeException("队列已空");
}
}
//查看队列
public void show(){
if(isEmpty()){
System.out.println("队列是空的");
}else {
for (int i = front+1; i <arr.length ; i++) {
System.out.printf("arr[%d]=%d\n",i,arr[i]);
}
}
}
//查看队列的头
public void head(){
if(isEmpty()){
System.out.println("队列是空的");
}else {
System.out.println(arr[front+1]);
}
}
}
循环队列
解决了假溢出的问题。留出一个空白格来判断数组的空或满。
四个变量:
- max 表示队列容量-1。max是数组的实际大小,但是因为留出了一个空白格,所有使用大小就小了一个。
- arr 表示队列
- rear 尾部指针,初始为0。指向队列最后一个元素的后一位,也就是指向空白格。
- front 头部指针,初始为0。指向队列第一个元素。
判断队列是否满:(rear+1%max)=front 队满时,rear指向最后一个元素的后一个位置,那么rear+1就会指向队头,也就是front,所以rear+1=front时队满,而因为rear已经是最后一个数字,我们要让他回到队头,开始新的循环,就要让他从头开始,就需要%max
判断队列是否空:front=rear 因为rear是最后一个数的后一个,front是第一个数位置,如果此时只剩一个数,front指向rear前一个位置,如果再出队列,front就会和rear相等,此时就空了。
求队列有效数字数量:(rear-front+max)%max 实际上就是rear和front之间的数的个数,但有可能是负数,这时候加上max的值才为真实的数量。
显示队列时i%max,防止越界,要通过%max让队列重新开始。
代码实现
package DataStructure.Queue;
import java.util.Scanner;
public class circleQueue {
public static void main(String[] args) {
CircleArrayQueue queue=new CircleArrayQueue(3);
Scanner sc=new Scanner(System.in);
boolean loop=true;
while (loop){
System.out.println("i:增加值到队列;o:出队列;s:展示队列;h:查看队头;e:退出");
char x=sc.next().charAt(0);
switch (x) {
case 'i':
System.out.println("请输入增加的值");
int n = sc.nextInt();
queue.in(n);
break;
case 'o':
try {
queue.out();
} catch (Exception e) {
e.printStackTrace();
}
break;
case 's':
queue.show();
break;
case 'h':
queue.head();
break;
case 'e':
sc.close();
loop = false;
break;
default:
break;
}
}
System.out.println("已退出");
}
}
class CircleArrayQueue{
//队列容量
private int max;
//队列头,指向队列第一个元素
private int front;
//队列尾,指向队列最后一个元素的后一个位置
private int rear;
//队列本体
private int[] arr;
public CircleArrayQueue(int max){
this.max=max;
this.front=0;
this.rear=0;
arr=new int[max];
}
//判断队列是否满
public boolean isFull(){
return (rear+1+max)%max==front;
}
//判断队列是否空
public boolean isEmpty(){
return front==rear;
}
//进队列
public void in(int n){
if(!isFull()){
arr[rear]=n;
rear=(rear+1+max)%max;
}else {
System.out.println("队列已满");
}
}
//出队列
public int out(){
if(!isEmpty()){
int x=arr[front];
front=(front+1+max)%max;
return x;
}else {
throw new RuntimeException("队列已空");
}
}
//查看队列
public void show(){
if(isEmpty()){
System.out.println("队列是空的");
}else {
for (int i = front; i <front+(rear-front+max)%max ; i++) {
System.out.printf("arr[%d]=%d\n",i%max,arr[i%max]);
}
}
}
//查看队列的头
public void head(){
if(isEmpty()){
System.out.println("队列是空的");
}else {
System.out.println(arr[front]);
}
}
}