队列是一种先进先出的数据结构
队列上的插入操作叫入队列,删除操作叫出队列
队列有对头,和队尾
就想超市结账排队一样,顾客总是排到队列的尾部(队尾),也就是说在队列的尾部入队列,队列的头部出队列。
如何在java中实现队列有两种选择,一种是通过数组实现,一种是通过链表实现。
数组实现的队列:
//队列接口
interface Queue<T>{
boolean enQueue(T k);
T deQueue();
boolean isEmpty();
void clear();
int length();
}
//顺序队列
class ArrayLinerQueue<T> implements Queue<T>{
private int size=0;
private int head=0;
private int tail=0;
private Object[] data = new Object[4];
@Override
public boolean enQueue(T k) {
// 判断是否需要进行数组扩容
if (tail >= data.length) {
resize();
}
System.out.println("enQueue: " + k);
data[tail++] = k;
size++;
return true;
}
/**
* 数组扩容
*/
private void resize() {
System.out.println("数组空间不够,扩容");
Object[] temp = new Object[data.length * 2];
for (int i = head; i < tail; i++) {
temp[i] = data[i];
data[i] = 0;
}
data = temp;
}
@Override
public T deQueue() {
if (size == 0) {
return null;
}
System.out.println("deQueue:"+(T)data[head]);
size--;
return (T)data[head++];
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void clear() {
// 将数组中的数据置为null, 方便GC进行回收
for (int i = 0; i < size; i++) {
data[size] = null;
}
size = 0;
head=0;
tail=0;
}
@Override
public int length() {
return size;
}
@Override
public String toString() {
return "ArrayQueue{" +
"size=" + size +
", head=" + head +
", tail=" + tail +
", data=" + Arrays.toString(data) +
'}';
}
}
//顺序循环队列
class ArrayCycleQueue<T> implements Queue<T>{
private int size=0;
private int head=0;
private int tail=0;
private Object[] data = new Object[4];
@Override
public boolean enQueue(T k) {
// 判断是否需要进行数组扩容
if (head==tail && head!=0) {
resize();
}
if (tail>=data.length && head>0){
tail=0;
}
System.out.println("enQueue: " + k);
data[tail++] = k;
size++;
return true;
}
/**
* 数组扩容
*/
private void resize() {
System.out.println("数组空间不够,扩容");
Object[] temp = new Object[data.length * 2];
for (int i = head+data.length; i < temp.length; i++,head++) {
temp[i] = data[head];
}
for (int i = 0; i < tail; i++) {
temp[i] = data[i];
}
data = temp;
}
@Override
public T deQueue() {
if (size == 0) {
return null;
}
System.out.println("deQueue:"+(T)data[head]);
size--;
return (T)data[head++];
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void clear() {
// 将数组中的数据置为null, 方便GC进行回收
for (int i = 0; i < size; i++) {
data[size] = null;
}
size = 0;
head=0;
tail=0;
}
@Override
public int length() {
return size;
}
@Override
public String toString() {
return "ArrayQueue{" +
"size=" + size +
", head=" + head +
", tail=" + tail +
", data=" + Arrays.toString(data) +
'}';
}
}
链表实现的队列
//链表实现队列
class LinkedListQueue<T> implements Queue<T>{
private int size=0;
private QueueNode head=null;
private QueueNode tail=null;
@Override
public boolean enQueue(T k) {
System.out.println("enQueue: " + k);
QueueNode queueNode = new QueueNode();
queueNode.setData(k);
if (tail==null){
tail=queueNode;
head=tail;
}else {
tail.setNext(queueNode);
tail=queueNode;
}
size++;
return true;
}
@Override
public T deQueue() {
if (size == 0) {
return null;
}
T tempdata = head.getData();
head=head.getNext();
System.out.println("deQueue:"+tempdata);
size--;
return tempdata;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void clear() {
size = 0;
head=null;
tail=null;
}
@Override
public int length() {
return size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
QueueNode temp = head;
while (temp!=null){
sb.append(temp.getData()+" ");
temp=temp.getNext();
}
return "LinkedListQueue{" +
"size=" + size +
", head=" + head.getData() +
", tail=" + tail.getData() +
", queue="+sb.toString()+
'}';
}
private class QueueNode{
private T data;
private QueueNode next;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public QueueNode getNext() {
return next;
}
public void setNext(QueueNode next) {
this.next = next;
}
}
}
测试
package com.zq.datastruct.linkedlist;
import java.util.Arrays;
/**
* Created by zhengshouzi on 2015/11/16.
*/
public class QueueTest {
public static void main(String[] args) {
Queue<Integer> queue =null;
System.out.println("------------------------arrayLinerQueue-------------------------------------");
queue=new ArrayLinerQueue();
queue.enQueue(32);
queue.enQueue(43);
queue.deQueue();
queue.enQueue(98);
System.out.println(queue.toString());
queue.enQueue(444);
System.out.println(queue.toString());
queue.enQueue(444);
System.out.println(queue.toString());
System.out.println("------------------------arrayCycleQueue-------------------------------------");
queue = new ArrayCycleQueue<>();
queue.enQueue(32);
queue.enQueue(43);
queue.deQueue();
queue.enQueue(98);
System.out.println(queue.toString());
queue.enQueue(444);
System.out.println(queue.toString());
queue.enQueue(567);
queue.enQueue(1200);
System.out.println(queue.toString());
System.out.println("------------------------linkedListQueue-------------------------------------");
queue = new LinkedListQueue();
queue.enQueue(32);
queue.enQueue(43);
queue.deQueue();
queue.enQueue(98);
System.out.println(queue.toString());
queue.enQueue(444);
System.out.println(queue.toString());
queue.enQueue(567);
queue.enQueue(1200);
System.out.println(queue.toString());
}
}
队列应用:
当多个任务分配给打印机时,为了防止冲突,创建一个队列,把任务入队,按先入先出的原则处理任务。
当多个用户要访问远程服务端的文件时,也用到队列,满足先来先服务的原则。
现如今众多的消息中间件的实现就是采用队列的思想。
……
有一个数学的分支,叫队列理论(queuing theory )。用来计算 预测用户在队中的等待时间,队的长度等等问题。
答案取决于用户到达队列的频率,用户的任务的处理时间。如果比较简单的情况,可以单单用分析解决。一个简单的例子就是,
一部电话,一个接线员。当一个电话打进来,如果接线员很忙,就电话放到等待线路后。接线员从队头开始应答。
凡事一切需要按照顺序来处理的数据,都可以用队列来实现,如果顺序带有优先级,可以用优先队列
队列和栈的说明:
队列比较适合于用链表实现:因为队列的操作在队列的两端进行,使用数组不方便
栈比较适合于用数组实现:而栈的操作始终在栈顶进行,始终在数组顶部操作就好了。