JAVA实现队列
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。
以下我们使用java来实现简单的队列,这里通过定义一个Queue类,使用相应的方法来实现入队,出队等简单操作。
这是Queue类的实现
class Queue{
private int front; //队列前
private int rear; //队列尾
private int maxSize; //队列最大大小
private int [] arr;
public Queue(int maxSize){
this.maxSize = maxSize;
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()){
arr[++rear] = n;
}else {
System.out.println("队列元素已满");
}
}
public int getHead(){//得到头元素
if(isEmpty()){
throw new RuntimeException("队列元素为空");
}
return arr[front+1];
}
public int removeHead(){//移除队头元素,出队
if(isEmpty()){
throw new RuntimeException("队列空,不能出队");
}
front++;
return arr[front];
}
public void showQueue(){//展示队列
if(isEmpty()){
System.out.println("队列空的,没有数据");
return;
}
for(int i=front+1;i<=rear;i++){
System.out.printf("%d ",arr[i]);
}
System.out.println();
}
}
这里的出队实际上是通过头指针front加一的方法使队头元素不显示而已。front永远指在队头第一个元素之前的一个位置。
很显然,顺序队列存在以下一些问题:
每次在队尾插入一个元素是,rear增1;每次在队头删除一个元素时,front增1。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。当front=rear时,队列中没有任何元素,称为空队列。当rear增加到指向分配的连续空间之外时,队列无法再插入新元素,但这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。
顺序队列中的溢出现象:
(1) "下溢"现象:当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。
(2)"真上溢"现象:当队列满时,做入队运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。
(3)"假上溢"现象:由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。
我们可以通过主函数进行测试:
public class ArrayQueue {
public static void main(String[] args) {
Queue queue =new Queue(3);
Scanner scanner = new Scanner(System.in);
boolean loop = true;
char input =' ';
while (loop){
System.out.println("e(exit):退出");
System.out.println("a(add):添加元素到队尾");
System.out.println("r(remove):移除元素从队头");
System.out.println("s(show):显示队列");
System.out.println("g(get):得到队头元素");
input = scanner.next().charAt(0);
switch (input){
case 'e':
scanner.close();
loop=false;
break;
case 'a':
System.out.println("请输入一个数字");
queue.addQueue(scanner.nextInt());
break;
case 'r':
try{
int i = queue.removeHead();
System.out.printf("出队元素是%d\n",i);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 's':
queue.showQueue();
break;
case 'g':
try{
int head = queue.getHead();
System.out.println("队头元素为:"+head);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
}
}
System.out.println("程序退出");
}
}
具体情况还是要自己运行体验滴。。。加油吧!!!
下一篇介绍循环队列,循环队列解决了队列“假上溢”的现象。